Refactor issue-facade to conform to the new ReusableCapabilitiesArchitecture specification, improving discoverability and establishing consistent patterns for capability integration. Architecture Changes: - Rename .feedback/ → feedback/ (visible user interface) - Rename CAPABILITY.yaml → CAPABILITY-issue-tracking.yaml (explicit family) - Keep .capability/ hidden (evolving implementation infrastructure) File Updates: - Updated all documentation references (.feedback → feedback) - Updated .capability/feedback script paths - Updated Makefile, README.md, CLAUDE.md, examples - Fixed CAPABILITY.yaml → CAPABILITY-issue-tracking.yaml references New Tools: - Created .capability/detach script for clean capability removal - Supports git submodule and directory-based integrations - Generates detachment manifest for re-integration guidance Rationale: - feedback/ is visible: encourages user participation, shows capability identity - .capability/ is hidden: implementation details that will evolve - CAPABILITY-<family>.yaml: explicit family declaration, supports multiple capabilities per repo - Underscore prefix pattern: flatter hierarchy, clear signal of integration This aligns with the principle that capabilities are conceptual units designed for natural language integration by devhumans and devagents, not just technical libraries. See ReusableCapabilitiesArchitecture.md for complete specification. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
16 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Issue Facade is a universal CLI for issue tracking that provides a unified interface to multiple issue tracking backends (GitHub, GitLab, Gitea, local SQLite). It implements the Facade Pattern to abstract away differences between various issue tracking systems, providing developers with a consistent CLI experience regardless of the underlying backend.
Development Commands
Installation & Setup
- Install for development:
pip install -e ".[dev]" - Install production:
pip install -e . - Clean build artifacts:
make issue-facade-clean
Testing
- Run all tests:
pytest tests/ - Run specific test file:
pytest tests/test_gitea_backend.py - Run with coverage:
pytest tests/ --cov=issue_tracker --cov-report=html --cov-report=term - Run integration tests:
pytest tests/test_gitea_integration.py -v
Code Quality
- Run linter:
make issue-facade-lint - Format code:
black issue_tracker/ tests/(line length: 100) - Sort imports:
isort issue_tracker/ tests/
CLI Usage
The project provides two entry points: issue and issue-tracker (both execute issue_tracker.cli.main:main)
Common commands:
issue list- List issuesissue show <number>- Show issue detailsissue create "Title"- Create new issueissue close <number>- Close issueissue backend list- List configured backendsissue sync- Synchronize with remote backend
Architecture
Core Design Pattern: Facade with Plugin Architecture
The codebase implements a plugin-based facade pattern with clear separation of concerns:
┌─────────────────────────────────────────┐
│ CLI Layer (Click) │
│ issue_tracker/cli/*.py │
└───────────────┬─────────────────────────┘
│
┌───────────────▼─────────────────────────┐
│ Core Domain Models │
│ issue_tracker/core/models.py │
│ (Issue, Label, User, etc.) │
└───────────────┬─────────────────────────┘
│
┌───────────────▼─────────────────────────┐
│ Backend Interface (ABC) │
│ issue_tracker/core/interfaces.py │
│ IssueBackend, LocalBackend, │
│ RemoteBackend, SyncableBackend │
└───────────────┬─────────────────────────┘
│
┌───────┴────────┐
│ │
┌───────▼──────┐ ┌──────▼───────┐
│Local Backend │ │Gitea Backend │
│ (SQLite) │ │ (REST API) │
└──────────────┘ └──────────────┘
Key Components
1. Core Domain Models (issue_tracker/core/models.py)
- Issue: Universal issue model with state management, label categorization, and domain logic
- Label: Supports categorization (priority/type/status/other) with cached properties
- User, Milestone, Comment: Supporting models
- IssueState, Priority, IssueType: Enumerations with backend mapping
The Issue model uses @cached_property for performance optimization and includes domain logic methods (close(), reopen(), add_label(), etc.) that enforce business rules.
2. Backend Interface (issue_tracker/core/interfaces.py)
- IssueBackend (ABC): Defines the contract all backends must implement
- LocalBackend, RemoteBackend: Marker interfaces for backend categorization
- SyncableBackend: Interface for backends supporting synchronization
- BackendCapabilities: Describes feature support per backend
- BackendFactory: Registry pattern for backend creation
Critical: All backends MUST implement the full IssueBackend interface. The interface includes:
- Connection management:
connect(),disconnect(),test_connection() - CRUD operations:
create_issue(),get_issue(),update_issue(),delete_issue() - Query operations:
list_issues(),search_issues() - Label, User, Milestone, Comment operations
- Optional:
bulk_update_issues()(if capabilities support it)
3. Backend Implementations
Local Backend (issue_tracker/backends/local/backend.py):
- Uses SQLite with schema defined in
schema.sql - Full offline functionality
- Serves as synchronization source of truth
- Implements
LocalBackendandSyncableBackend
Gitea Backend (issue_tracker/backends/gitea/backend.py):
- REST API integration with Gitea instances
- Rate limiting and error handling
- ID mapping between local and remote issues
- Implements
RemoteBackendandSyncableBackend
4. CLI Layer (issue_tracker/cli/)
- main.py: Entry point, Click group setup, command registration
- commands.py: Core issue operations (list, show, create, close)
- backend_commands.py: Backend management (add, list, switch)
- sync_commands.py: Synchronization operations
- utils.py: Helper functions for formatting and backend access
ID Mapping Strategy
The system uses a dual-ID approach for cross-backend synchronization:
id: Universal ID (UUID for local, external ID for remote)number: Human-readable sequential number (user-facing)backend_id: Backend-specific identifier for sync
When syncing, backends maintain mappings between local numbers and remote IDs. The Gitea backend stores this in sync_metadata on the Issue model.
State Management
IssueState enum provides universal states with backend-specific mapping via to_backend_string():
- OPEN, CLOSED, IN_PROGRESS, BLOCKED
- Some backends (like Gitea) only support OPEN/CLOSED, so IN_PROGRESS and BLOCKED map to OPEN
Testing Strategy
Test Organization
test_gitea_backend.py: Unit tests for Gitea backend with mocked APItest_gitea_integration.py: Full integration tests with real Gitea instancetest_cli_commands.py: CLI command testing
Integration Tests
The integration tests (test_gitea_integration.py) expect a Gitea instance at http://localhost:3000 with test credentials. They create a temporary test repository, run full CRUD operations, and clean up afterwards.
Important: Integration tests use pytest markers:
@pytest.mark.integration- Integration tests (slower)@pytest.mark.unit- Unit tests (fast)
Run only unit tests: pytest -m unit
Run only integration tests: pytest -m integration
Common Development Tasks
Adding a New Backend
- Create backend package in
issue_tracker/backends/<name>/ - Implement
IssueBackendinterface (or extendLocalBackend/RemoteBackend) - Implement all abstract methods from the interface
- Define
BackendCapabilitiesto specify supported features - Register backend in
BackendFactory(typically in__init__.py) - Add configuration handling in CLI backend commands
- Write unit tests with mocked external dependencies
- Write integration tests if applicable
Modifying the Issue Model
When changing issue_tracker/core/models.py:
- Update the
Issuedataclass definition - Update
to_dict()serialization method - Invalidate caches if adding/modifying label-dependent properties
- Update all backend implementations to handle new fields
- Update database schema in
backends/local/schema.sql - Write migration logic if modifying existing fields
Adding CLI Commands
- Add command function in appropriate file (
commands.py,backend_commands.py, etc.) - Use
@click.command()decorator with appropriate options - Call
get_backend(ctx)to retrieve the active backend - Use
format_issue()orformat_issue_list()fromutils.pyfor consistent output - Handle errors with
raise click.ClickException(message) - Register command in
main.pyif creating new command group
Configuration
Project Configuration (pyproject.toml)
- Entry points:
issueandissue-trackercommands - Dependencies: click, requests, python-dateutil
- Optional dependencies: dev, docs, gitea, github, jira
- Code style: Black (line-length=100), isort (profile="black")
- Test markers: unit, integration, slow
Makefile Integration
The capability integrates with the parent markitect project via Makefile:
- Prefixed targets:
issue-facade-*for development commands - Unprefixed targets:
issue-*for user-facing CLI operations - Uses
pip install -efor editable installation
Important Patterns and Conventions
Error Handling
- Backend-specific errors inherit from base exceptions (e.g.,
GiteaAPIError) - CLI commands convert exceptions to
click.ClickExceptionwith user-friendly messages - Use specific exception types for rate limiting, authentication, network issues
Type Hints
- Mypy strict mode enabled (
disallow_untyped_defs = true) - All functions must have type annotations
- Use
Optional[T]for nullable types - Use
List[T],Dict[K, V]fromtypingmodule (Python 3.8 compatibility)
Performance Optimizations
- Use
@cached_propertyfor expensive computations (e.g., label categorization) - Call
invalidate_cache()when modifying cached data - Single-pass algorithms for label categorization in Issue model
Synchronization
When implementing sync:
- Local backend is source of truth
- Remote backends track last sync timestamp
- Use
get_issues_modified_since()for incremental sync - Handle conflicts via
SyncableBackend.resolve_sync_conflict() - Store sync metadata in Issue.sync_metadata dict
Dependencies and External Systems
Runtime Dependencies
- click: CLI framework (>=8.0.0)
- requests: HTTP client for remote backends (>=2.25.0)
- python-dateutil: Date/time parsing (>=2.8.0)
Development Dependencies
- pytest: Testing framework with markers support
- pytest-cov: Coverage reporting
- pytest-mock: Mocking utilities
- black, isort, flake8, mypy: Code quality tools
External Systems
- Gitea API: REST API at
/api/v1/endpoints - SQLite: Local database (no server required)
- Future: GitHub API, GitLab API, JIRA API
Repository Context
This is a capability within the larger markitect project (/capabilities/issue-facade/). The capability:
- Can be installed independently via
pip install -e . - Integrates with parent project via Makefile targets
- Follows markitect capability conventions for structure and naming
Feedback and Continuous Improvement
This capability implements the feedback pattern - a lightweight, unstructured feedback loop for continuous improvement based on real-world usage from master projects integrating this capability.
Overview
The feedback system consists of:
feedback/directory: Stores all feedback with minimal organization.capability/feedbackCLI tool: Standalone tool for submitting and managing feedback- No structure imposement: Accept any text/markdown format
- Capability-owned: Maintainers organize and prioritize feedback
Directory Structure
.feedback/
├── inbound/ # New feedback from users (unreviewed)
├── reviewed/ # Feedback reviewed by maintainers
├── archived/ # Resolved or outdated feedback
└── README.md # Complete documentation
For Users: Submitting Feedback
Users of issue-facade (master projects integrating it) can submit feedback in multiple ways:
Option 1: Using feedback CLI
# Quick text feedback
./.capability/feedback submit "The sync command is slow with 1000+ issues"
# From a file
./.capability/feedback submit detailed-feedback.md
# With metadata
./.capability/feedback submit "Bug report" --category=bug --contact=me@email.com
Option 2: Direct file drop (no CLI needed)
# Just create a markdown file in inbound/
cat > feedback/inbound/$(date +%Y%m%d)-sync-issue.md << 'EOF'
The sync is taking 10+ minutes with our 5000-issue repo.
Would love to see progress indicators or batch processing.
EOF
Option 3: From master project
cd my-master-project
echo "Feedback about issue-facade..." > feedback.md
cp feedback.md capabilities/issue-facade/feedback/inbound/$(date +%Y%m%d)-feedback.md
For Maintainers: Processing Feedback
List and review feedback:
# List pending feedback
./.capability/feedback list
# Show specific feedback
./.capability/feedback show 20251217-103045-abc12345.md
# Show statistics
./.capability/feedback stats
Process feedback:
# Mark as reviewed
./.capability/feedback review 20251217-103045-abc12345.md
# Create issue from feedback
./.capability/feedback review 20251217-103045-abc12345.md --create-issue
# Archive when resolved
./.capability/feedback archive 20251217-103045-abc12345.md
Manual workflow (without CLI):
# 1. List new feedback
ls -lt feedback/inbound/
# 2. Read feedback
cat feedback/inbound/20251217-103045-sync-issue.md
# 3. Take action (create issue, fix, document)
issue create "Feature: Show sync progress" \
--description "$(cat feedback/inbound/20251217-103045-sync-issue.md)" \
--label=feedback --label=feature
# 4. Move to reviewed
mv feedback/inbound/20251217-103045-sync-issue.md feedback/reviewed/
Integration with Development Workflow
Feedback informs:
- Roadmap prioritization: Most requested features get priority
- Bug triage: Real-world issues from production usage
- Documentation improvements: Where users struggle
- UX enhancements: Friction points in actual usage
Review rhythm:
- Daily: Quick scan of new feedback
- Weekly: Deep review, create issues, respond to users
- Monthly: Archive old feedback, analyze trends
Feedback Pattern (Reusable Across Capabilities)
The feedback system is capability-agnostic and can be copied to any markitect capability:
-
Copy the pattern:
mkdir -p feedback/inbound feedback/reviewed feedback/archived cp /path/to/feedback-template/README.md .feedback/ cp /path/to/feedback-template/feedback .capability/ chmod +x .capability/feedback -
Document in CAPABILITY-issue-tracking.yaml:
feedback: enabled: true method: feedback-capability submission: cli: ".capability/feedback submit 'Your feedback'" directory: "feedback/inbound/" -
Add to Makefile (optional):
feedback: @./.capability/feedback submit "$(MSG)"
Future Evolution:
- When capability becomes a service, add API endpoint:
POST /api/feedback - API writes to same
feedback/inbound/directory - Maintains consistency across CLI, file drop, and API submission
Why This Pattern?
- Decentralized: Each capability owns its feedback
- Flexible: No forms, no required structure
- Durable: Plain files survive system changes
- Auditable: Git tracks all feedback
- Actionable: Feedback lives where maintainers work
- Scalable: Works for 1 user or 1000 users
- Future-proof: Can evolve to CLI/API while maintaining structure
See feedback/README.md for complete documentation.