agentleFS
ebibibiebibibi/claude-code-discord-bridge/.claude/skills/tdd/SKILL.md

tdd

Skill66 starsChanged 9 months agoMITView on GitHub

Enforce test-driven development — write tests FIRST, then implement. Mandatory for new features and bug fixes.

  • Deletes or force-pushes

We split this skill into the rules it gives an agent

4 rules. 0 are common, 3 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 185 edited versions we read keep these.

  • 3

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    When adding features or fixing bugs in claude-code-discord-bridge, you MUST write tests before writing implementation code.

    line 10
  2. Distinctive:

    Write tests that describe the desired behavior.

    line 23
  3. Distinctive:

    If tests pass before you write any implementation, your tests are wrong.

    line 30
  4. Distinctive:

    Write the minimum code to make the tests pass.

    line 34

“Common” is measured: kept by at least 6 in 10 of the 185 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

TDD — Test-Driven Development (Enforced)

This is not a suggestion. This is the workflow.

When adding features or fixing bugs in claude-code-discord-bridge, you MUST write tests before writing implementation code. No exceptions.

When to Activate

  • Adding any new feature or functionality
  • Fixing a bug (write a test that reproduces the bug FIRST)
  • Refactoring code (ensure existing tests pass, add missing ones)
  • Adding a new Cog, parser rule, UI component, or database operation

The Cycle: RED → GREEN → REFACTOR

Step 1: RED — Write Failing Tests

Write tests that describe the desired behavior. Run them. They must fail.

uv run pytest tests/test_new_feature.py -v
# Expected: FAILED (because the code doesn't exist yet)

If tests pass before you write any implementation, your tests are wrong.

Step 2: GREEN — Write Minimal Implementation

Write the minimum code to make the tests pass. No more.

uv run pytest tests/test_new_feature.py -v
# Expected: PASSED

Step 3: REFACTOR — Clean Up

Improve the implementation while keeping all tests green. Then run the full suite:

uv run pytest tests/ -v --cov=claude_discord --cov-report=term-missing

Step 4: VERIFY — Lint + Format + Full Suite

uv run ruff check claude_discord/
uv run ruff format claude_discord/
uv run pytest tests/ -v --cov=claude_discord

What to Test First (by module type)

New Parser Rule

# tests/test_parser.py — Write THIS first
def test_parse_new_event_type():
    line = '{"type":"new_type","data":"value"}'
    event = parse_line(line)
    assert event is not None
    assert event.message_type == MessageType.ASSISTANT

def test_parse_new_event_type_missing_data():
    line = '{"type":"new_type"}'
    event = parse_line(line)
    assert event is not None  # Should handle gracefully

# THEN implement in claude_discord/claude/parser.py

New Cog Command

# tests/test_new_cog.py — Write THIS first
from unittest.mock import AsyncMock, MagicMock

def test_rejects_unauthorized_user():
    cog = MyCog(bot=MagicMock(), allowed_user_ids={111})
    assert cog._is_authorized(999) is False

def test_accepts_authorized_user():
    cog = MyCog(bot=MagicMock(), allowed_user_ids={111})
    assert cog._is_authorized(111) is True

def test_validates_input_format():
    # Test that invalid input is rejected before reaching CLI
    assert not re.match(r"^[\w-]+$", "invalid; rm -rf /")

# THEN implement in claude_discord/cogs/my_cog.py

New Chunker Behavior

# tests/test_chunker.py — Write THIS first
def test_chunk_with_nested_code_blocks():
    text = "```python\n```nested```\n```"
    chunks = chunk_message(text)
    # Verify code blocks are not broken
    for chunk in chunks:
        assert chunk.count("```") % 2 == 0  # Even number = balanced

def test_chunk_unicode_content():
    text = "日本語テスト 🎉" * 500
    chunks = chunk_message(text)
    assert all(len(c.encode("utf-8")) <= 8000 for c in chunks)

# THEN implement the fix in claude_discord/discord_ui/chunker.py

Bug Fix

# tests/test_bug_123.py — Write THIS first
def test_session_id_with_uppercase_rejected():
    """Bug #123: Session IDs with uppercase hex were accepted."""
    runner = ClaudeRunner()
    with pytest.raises(ValueError):
        runner._build_args("hello", session_id="ABC-DEF")

# Confirm the test FAILS with current code
# THEN fix the regex in runner.py
# THEN confirm the test PASSES

Database Operation

# tests/test_repository.py — Write THIS first
async def test_save_overwrites_existing(repo):
    await repo.save(thread_id=123, session_id="old-id")
    await repo.save(thread_id=123, session_id="new-id")
    result = await repo.get_session_id(thread_id=123)
    assert result == "new-id"

async def test_concurrent_saves(repo):
    import asyncio
    tasks = [
        repo.save(thread_id=i, session_id=f"session-{i}")
        for i in range(100)
    ]
    await asyncio.gather(*tasks)
    # All should succeed without errors

# THEN implement or verify in claude_discord/database/repository.py

Coverage Requirements

ModuleTargetRationale
parser.py90%+Pure logic, no dependencies, easy to test
chunker.py90%+Pure logic, edge cases are critical
types.py90%+Data structures and enums
repository.py90%+Real SQLite, no mocking needed
runner.py60%+Test args/env building; subprocess is harder
Cogs30%+Discord mocking is heavy; test validation logic
status.py30%+Async + Discord API mocking
Overall50%+And always increasing

Anti-Patterns (Don't Do This)

Writing implementation first, tests later

❌ "I'll write the code first and add tests after"
✅ "I'll write the test first, watch it fail, then implement"

Testing implementation details

# ❌ Bad: Testing internal state
assert runner._process is not None

# ✅ Good: Testing observable behavior
args = runner._build_args("hello", None)
assert args[-1] == "hello"

Skipping the RED step

❌ Writing a test that passes immediately
✅ Writing a test, running it, confirming it FAILS, then implementing

Over-mocking

# ❌ Bad: Mocking everything
mock_everything = MagicMock()
result = function_under_test(mock_everything)
# What are you even testing?

# ✅ Good: Mock only external boundaries
real_runner = ClaudeRunner(command="claude")
args = real_runner._build_args("test prompt", None)
assert "--" in args

Quick Reference

# Run specific test file
uv run pytest tests/test_parser.py -v

# Run specific test
uv run pytest tests/test_parser.py::test_parse_system_message -v

# Run with coverage
uv run pytest tests/ -v --cov=claude_discord --cov-report=term-missing

# Stop on first failure
uv run pytest tests/ -x

# Show local variables on failure
uv run pytest tests/ -v --tb=short -l

Download now (ZIP)

  • Other versions193 projects use a version of this.

    Word for word · 1

    1. ebibibi/ebi-agent-chat-relay★ 66100% same

    Edited · 0

    None found.

    Wrote their own version · 192

    1. mattpocock/skills★ 309ksame name
    2. Yeachan-Heo/oh-my-claude-sisyphus★ 40ksame name
    3. Yeachan-Heo/oh-my-claudecode★ 40ksame name
    4. QuivrHQ/quivr★ 40ksame name
    5. ccusage/ccusage★ 19ksame name
    6. ryoppippi/ccusage★ 19ksame name
    7. MODSetter/SurfSense★ 17ksame name
    8. GreyDGL/PentestGPT★ 16ksame name
    9. open-metadata/OpenMetadata★ 16ksame name
    10. prowler-cloud/prowler★ 15ksame name

    182 more not listed

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • Used alongsideProjects with it also use ketchup-video, principle-laziness-protocol and 10 more.

    Other files people use alongside this one.

    Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
    • 3metaJunSkill

      ketchup-video

      Catch the user up like /ketchup, with a short subtitled video of slides for what happened and the waiting calls as text under it. Use for /ketchup-video.

      Also in 10 projects that use this

    • jaydubya818Skill

      principle-laziness-protocol

      Apply when a refactor is adding wrappers or abstractions instead of simplifying.

      Also in 43 projects that use this

    • jaydubya818Skill

      principle-make-operations-idempotent

      Apply when an operation must tolerate retries after partial completion.

      Also in 43 projects that use this

    • bnemaSkill

      setup-pstack

      Configure which Pi models pstack uses per role. Detects available provider/model specs and writes pstack's user configuration. Use for /setup-pstack, "configure pstack models", or changing pstack model choices.

      Also in 25 projects that use this

    • +8 more from jaydubya818
  • In this repository9 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.