2025-09-21 23:46:46 +02:00
# MarkiTect - Advanced Markdown Engine
# Makefile for common development tasks
2025-09-22 01:28:55 +02:00
.PHONY : help setup install test build clean update status dev lint format check -deps venv -status update -digest add -diary -entry list -issues show -issue list -open -issues test -from -issue start -issue add -test finish -issue workspace -status
2025-09-21 23:46:46 +02:00
# Default target
help :
@echo "MarkiTect Development Commands"
@echo "=============================="
@echo ""
2025-09-22 00:18:24 +02:00
@echo "Environment Status:"
@$( MAKE) --no-print-directory venv-status
@echo ""
2025-09-21 23:46:46 +02:00
@echo "Setup & Installation:"
@echo " setup - Initial project setup (venv + install)"
@echo " install - Install package in development mode"
@echo " dev - Install with development dependencies"
2025-09-22 00:18:24 +02:00
@echo " venv-status - Check if venv is active"
2025-09-21 23:46:46 +02:00
@echo ""
@echo "Development:"
@echo " test - Run all tests"
@echo " build - Build the package"
@echo " lint - Run code linting"
@echo " format - Format code"
@echo ""
@echo "Maintenance:"
@echo " update - Update from upstream (git + submodules)"
@echo " status - Show git status for repo and submodules"
@echo " clean - Clean build artifacts"
@echo " check-deps - Check dependency status"
2025-09-22 00:37:04 +02:00
@echo ""
@echo "Documentation:"
2025-09-22 00:49:23 +02:00
@echo " update-digest - Update ProjectStatusDigest.md (requires Claude Code)"
@echo " add-diary-entry - Add new entry to ProjectDiary.md (requires Claude Code)"
2025-09-22 01:11:00 +02:00
@echo ""
@echo "Issue Management:"
@echo " list-issues - Show all gitea issues with status and priority"
@echo " list-open-issues - Show only open issues (active backlog)"
@echo " show-issue NUM=X - Show detailed view of specific issue"
2025-09-22 01:17:54 +02:00
@echo ""
@echo "Test-Driven Development:"
@echo " test-from-issue NUM=X - Generate test skeleton from issue (requires Claude Code)"
2025-09-22 01:28:55 +02:00
@echo ""
@echo "Issue Workspace:"
@echo " start-issue NUM=X - Start working on issue (creates workspace)"
@echo " add-test - Add test to current issue workspace"
@echo " workspace-status - Show current workspace state"
@echo " finish-issue - Complete issue work (moves tests to main)"
2025-09-21 23:46:46 +02:00
# Python and virtual environment setup
PYTHON := python3
VENV := .venv
VENV_PYTHON := $( VENV) /bin/python
VENV_PIP := $( VENV) /bin/pip
2025-09-22 00:18:24 +02:00
# Check virtual environment status (read-only)
venv-status :
@if [ -f $( VENV) /bin/activate ] && [ -f $( VENV) /bin/python ] ; then \
if [ -n " $$ VIRTUAL_ENV " ] && [ " $$ VIRTUAL_ENV " = " $$ (realpath $( VENV) ) " ] ; then \
echo " ✅ Virtual environment: Active in current shell" ; \
elif [ -n " $$ VIRTUAL_ENV " ] ; then \
echo " ⚠️ Virtual environment: Different venv active ( $$ VIRTUAL_ENV) " ; \
echo " Run 'deactivate' then 'source $( VENV) /bin/activate' " ; \
else \
echo " 📁 Virtual environment: Ready but not activated" ; \
echo " Run 'source $( VENV) /bin/activate' to activate " ; \
fi ; \
else \
echo " ❌ Virtual environment: Not found" ; \
echo " Run 'make setup' to create and configure" ; \
fi
2025-09-21 23:46:46 +02:00
# Setup virtual environment and install package
setup : $( VENV ) /bin /activate install
@echo "✅ Project setup complete!"
$(VENV)/bin/activate :
@echo "🔧 Creating virtual environment..."
$( PYTHON) -m venv $( VENV)
$( VENV_PIP) install --upgrade pip setuptools wheel
# Install package in development mode
install : $( VENV ) /bin /activate
@echo "📦 Installing MarkiTect in development mode..."
$( VENV_PIP) install -e .
# Install with development dependencies
dev : install
@echo "🛠️ Installing development dependencies..."
$( VENV_PIP) install pytest pytest-cov black flake8 mypy
# Run tests
test : $( VENV ) /bin /activate
@echo "🧪 Running tests..."
@if [ -f $( VENV) /bin/pytest ] ; then \
$( VENV) /bin/pytest tests/ -v; \
else \
$( VENV_PYTHON) -m pytest tests/ -v 2>/dev/null || \
$( VENV_PYTHON) -m unittest discover tests/ -v; \
fi
# Build the package
build : $( VENV ) /bin /activate
@echo "🏗️ Building package..."
$( VENV_PYTHON) -m build 2>/dev/null || \
$( VENV_PIP) install build && $( VENV_PYTHON) -m build
# Code linting
lint : $( VENV ) /bin /activate
@echo "🔍 Running linting..."
@if [ -f $( VENV) /bin/flake8 ] ; then \
$( VENV) /bin/flake8 markitect/ tests/; \
else \
echo "⚠️ flake8 not installed. Run 'make dev' first." ; \
fi
# Code formatting
format : $( VENV ) /bin /activate
@echo "✨ Formatting code..."
@if [ -f $( VENV) /bin/black ] ; then \
$( VENV) /bin/black markitect/ tests/; \
else \
echo "⚠️ black not installed. Run 'make dev' first." ; \
fi
# Update from upstream
update :
@echo "🔄 Updating from upstream..."
@git status --porcelain | grep -q . && echo "⚠️ Working directory not clean. Commit or stash changes first." && exit 1 || true
git pull origin main
git submodule update --remote
@if git status --porcelain | grep -q "wiki" ; then \
echo "📝 Committing wiki submodule update..." ; \
git add wiki; \
git commit -m "Update wiki submodule to latest" ; \
fi
@echo "✅ Update complete!"
# Show git status
status :
@echo "📊 Repository Status"
@echo "==================="
@echo ""
@echo "Main Repository:"
git status --short
@echo ""
@echo "Wiki Submodule:"
@cd wiki && git status --short
@echo ""
@echo "Recent Commits:"
git log --oneline -5
# Clean build artifacts
clean :
@echo "🧹 Cleaning build artifacts..."
rm -rf build/
rm -rf dist/
rm -rf *.egg-info/
find . -type d -name __pycache__ -exec rm -rf { } + 2>/dev/null || true
find . -name "*.pyc" -delete 2>/dev/null || true
@echo "✅ Clean complete!"
# Check dependency status
check-deps : $( VENV ) /bin /activate
@echo "📋 Dependency Status"
@echo "==================="
@echo ""
@echo "Python version:"
$( VENV_PYTHON) --version
@echo ""
@echo "Installed packages:"
$( VENV_PIP) list
@echo ""
@echo "Project dependencies:"
2025-09-22 00:18:24 +02:00
$( VENV_PIP) check
2025-09-22 00:37:04 +02:00
# Update project status digest (requires Claude Code)
update-digest :
@echo "🔍 Checking for Claude Code availability..."
@if ! command -v claude >/dev/null 2>& 1; then \
echo "❌ Claude Code not found in PATH" ; \
echo " This target requires Claude Code CLI to be installed" ; \
echo " Visit: https://claude.ai/code for installation instructions" ; \
exit 1; \
fi
@echo "✅ Claude Code found"
@echo "📝 Updating ProjectStatusDigest.md..."
@echo " Please ask Claude Code to update the project digest based on current state"
@echo " Command: 'Please update ProjectStatusDigest.md with the current project state'"
@echo ""
@echo "💡 Tip: You can also manually edit ProjectStatusDigest.md if needed"
2025-09-22 00:49:23 +02:00
# Add new entry to project diary (requires Claude Code)
add-diary-entry :
@echo "🔍 Checking for Claude Code availability..."
@if ! command -v claude >/dev/null 2>& 1; then \
echo "❌ Claude Code not found in PATH" ; \
echo " This target requires Claude Code CLI to be installed" ; \
echo " Visit: https://claude.ai/code for installation instructions" ; \
exit 1; \
fi
@echo "✅ Claude Code found"
@if [ ! -f ProjectDiary.md ] ; then \
echo "❌ ProjectDiary.md not found" ; \
echo " Create the diary file first or run this from the project root" ; \
exit 1; \
fi
@echo "📖 Adding new entry to ProjectDiary.md..."
@echo " Please ask Claude Code to add a new diary entry for recent work"
@echo " Command: 'Please add a new entry to ProjectDiary.md summarizing recent progress'"
@echo ""
@echo "📋 Entry should include:"
@echo " - Date ( $( shell date +%Y-%m-%d) ) "
@echo " - One-line progress characterization"
@echo " - Contributors since last entry"
@echo " - Time estimate and AI token usage"
@echo " - One paragraph work summary"
@echo ""
@echo "💡 Tip: New entries are added to the top for reverse chronological order"
2025-09-22 01:11:00 +02:00
# Git repository and API configuration
GITEA_URL := http://92.205.130.254:32166
REPO_OWNER := coulomb
REPO_NAME := markitect_project
ISSUES_API := $( GITEA_URL) /api/v1/repos/$( REPO_OWNER) /$( REPO_NAME) /issues
2025-09-22 01:28:55 +02:00
# Issue workspace configuration
WORKSPACE_DIR := .markitect_workspace
CURRENT_ISSUE_FILE := $( WORKSPACE_DIR) /current_issue.json
2025-09-22 01:11:00 +02:00
# List all gitea issues
list-issues :
@echo "📋 MarkiTect Issues from Gitea Repository"
@echo "========================================"
@echo ""
@if ! command -v curl >/dev/null 2>& 1; then \
echo "❌ curl not found - required for API access" ; \
exit 1; \
fi
@if ! command -v jq >/dev/null 2>& 1; then \
echo "⚠️ jq not found - using basic formatting" ; \
echo " Install jq for better formatting: sudo apt install jq" ; \
curl -s " $( ISSUES_API) " | head -20; \
else \
curl -s " $( ISSUES_API) " | jq -r '.[] | "[\(.state | ascii_upcase)] #\(.number): \(.title)\n Created: \(.created_at[:10]) | Updated: \(.updated_at[:10])\n \(.body[:80])...\n"' | head -40; \
fi
@echo ""
@echo "💡 Tip: Use 'make show-issue NUM=X' to see full details"
# Show detailed view of a specific issue
show-issue :
@if [ -z " $( NUM) " ] ; then \
echo "❌ Please specify issue number: make show-issue NUM=5" ; \
exit 1; \
fi
@if ! command -v curl >/dev/null 2>& 1; then \
echo "❌ curl not found - required for API access" ; \
exit 1; \
fi
@echo " 🔍 Issue # $( NUM) Details "
@echo "======================="
@echo ""
@if ! command -v jq >/dev/null 2>& 1; then \
echo "⚠️ jq not found - using basic formatting" ; \
curl -s " $( ISSUES_API) / $( NUM) " ; \
else \
curl -s " $( ISSUES_API) / $( NUM) " | jq -r 'if . == null or .message then "❌ Issue #$(NUM) not found or API error" else "**Title:** " + .title + "\n**Status:** " + (.state | ascii_upcase) + "\n**Number:** #" + (.number | tostring) + "\n**Created:** " + (.created_at[:10]) + " by " + (.user.full_name // .user.login) + "\n**Updated:** " + (.updated_at[:10]) + "\n**URL:** " + .html_url + "\n\n**Description:**\n" + .body end' 2>/dev/null || echo " ❌ Issue # $( NUM) not found or API error " ; \
fi
@echo ""
@echo "💡 Tip: Use 'make list-issues' to see all issues"
# List only open issues (active backlog)
list-open-issues :
@echo "📋 Open MarkiTect Issues (Active Backlog)"
@echo "========================================"
@echo ""
@if ! command -v curl >/dev/null 2>& 1; then \
echo "❌ curl not found - required for API access" ; \
exit 1; \
fi
@if ! command -v jq >/dev/null 2>& 1; then \
echo "⚠️ jq not found - using basic formatting" ; \
curl -s " $( ISSUES_API) ?state=open " | head -20; \
else \
curl -s " $( ISSUES_API) ?state=open " | jq -r '.[] | "[OPEN] #\(.number): \(.title)\n Created: \(.created_at[:10]) | Updated: \(.updated_at[:10])\n \(.body[:80])...\n"' | head -40; \
fi
@echo ""
@echo "💡 Tip: Use 'make show-issue NUM=X' for full details or 'make list-issues' for all issues"
2025-09-22 01:17:54 +02:00
# Generate test skeleton from gitea issue (requires Claude Code)
test-from-issue :
@if [ -z " $( NUM) " ] ; then \
echo "❌ Please specify issue number: make test-from-issue NUM=1" ; \
exit 1; \
fi
@echo "🔍 Checking for Claude Code availability..."
@if ! command -v claude >/dev/null 2>& 1; then \
echo "❌ Claude Code not found in PATH" ; \
echo " This target requires Claude Code CLI to be installed" ; \
echo " Visit: https://claude.ai/code for installation instructions" ; \
exit 1; \
fi
@echo "✅ Claude Code found"
@echo "🔍 Checking for curl..."
@if ! command -v curl >/dev/null 2>& 1; then \
echo "❌ curl not found - required for API access" ; \
exit 1; \
fi
@echo "✅ curl found"
@echo " 📋 Fetching issue # $( NUM) details... "
@curl -s " $( ISSUES_API) / $( NUM) " | jq -r 'if .title then "✅ Issue #$(NUM): " + .title + "\n\n🧪 Generating test skeleton...\n Please ask Claude Code to generate a test for this issue:\n\n Command: ' "'" 'Generate a test skeleton for issue #$(NUM)' "'" '\n\n📋 Issue Details:\n Title: " + .title + "\n Description: " + .body + "\n\n📝 Test Requirements:\n - Follow TDD principles (test first, then implementation)\n - Use pytest framework (existing project convention)\n - Place test in tests/ directory\n - Name test file: test_issue_$(NUM)_*.py\n - Include docstring referencing issue #$(NUM)\n - Test should initially fail (red state)\n\n💡 After generation, run ' "'" 'make test' "'" ' to verify test fails initially" else "❌ Issue #$(NUM) not found or API error\n Use ' "'" 'make list-open-issues' "'" ' to see available issues" end' 2>/dev/null || echo " ❌ Issue # $( NUM) not found or API error "
2025-09-22 01:28:55 +02:00
# Start working on an issue (creates workspace)
start-issue :
@if [ -z " $( NUM) " ] ; then \
echo "❌ Please specify issue number: make start-issue NUM=1" ; \
exit 1; \
fi
@echo " 🔍 Starting work on issue # $( NUM) ... "
@if [ -f " $( CURRENT_ISSUE_FILE) " ] ; then \
CURRENT = $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.number // "unknown"' ) ; \
echo " ⚠️ Already working on issue # $$ CURRENT " ; \
echo " Run 'make finish-issue' first or 'make workspace-status' to see details" ; \
exit 1; \
fi
@if ! command -v curl >/dev/null 2>& 1 || ! command -v jq >/dev/null 2>& 1; then \
echo "❌ curl and jq required for workspace management" ; \
exit 1; \
fi
@echo " 📋 Fetching issue # $( NUM) details... "
@ISSUE_DATA= $$ ( curl -s " $( ISSUES_API) / $( NUM) " 2>/dev/null) ; \
if echo " $$ ISSUE_DATA " | jq -e '.title' >/dev/null 2>& 1; then \
mkdir -p " $( WORKSPACE_DIR) /issue_ $( NUM) /tests " ; \
echo " $$ ISSUE_DATA " | jq '{number: .number, title: .title, body: .body, state: .state, created_at: .created_at, html_url: .html_url}' > " $( CURRENT_ISSUE_FILE) " ; \
echo " $$ ISSUE_DATA " | jq -r '"# Issue #" + (.number | tostring) + ": " + .title + "\n\n## Description\n" + .body + "\n\n## Requirements Breakdown\n\n- [ ] TODO: Break down requirements into testable scenarios\n- [ ] TODO: Identify edge cases\n- [ ] TODO: Define acceptance criteria\n\n## Test Plan\n\n- [ ] TODO: List specific test scenarios to implement\n"' > " $( WORKSPACE_DIR) /issue_ $( NUM) /requirements.md " ; \
echo " # Test Plan for Issue # $( NUM) " > " $( WORKSPACE_DIR) /issue_ $( NUM) /test_plan.md " ; \
echo "" >> " $( WORKSPACE_DIR) /issue_ $( NUM) /test_plan.md " ; \
echo "## Test Scenarios" >> " $( WORKSPACE_DIR) /issue_ $( NUM) /test_plan.md " ; \
echo "" >> " $( WORKSPACE_DIR) /issue_ $( NUM) /test_plan.md " ; \
echo "- [ ] TODO: Add specific test scenarios" >> " $( WORKSPACE_DIR) /issue_ $( NUM) /test_plan.md " ; \
echo " ✅ Workspace created for issue # $( NUM) " ; \
echo " 📁 Workspace: $( WORKSPACE_DIR) /issue_ $( NUM) / " ; \
echo " 📋 Requirements: $( WORKSPACE_DIR) /issue_ $( NUM) /requirements.md " ; \
echo " 🧪 Test plan: $( WORKSPACE_DIR) /issue_ $( NUM) /test_plan.md " ; \
echo "" ; \
echo "💡 Next steps:" ; \
echo " 1. Review requirements.md and break down the issue" ; \
echo " 2. Plan test scenarios in test_plan.md" ; \
echo " 3. Use 'make add-test' to generate tests" ; \
echo " 4. Use 'make finish-issue' when complete" ; \
else \
echo " ❌ Issue # $( NUM) not found or API error " ; \
echo " Use 'make list-open-issues' to see available issues" ; \
fi
# Add test to current issue workspace
add-test :
@if [ ! -f " $( CURRENT_ISSUE_FILE) " ] ; then \
echo "❌ No active issue workspace" ; \
echo " Run 'make start-issue NUM=X' first" ; \
exit 1; \
fi
@if ! command -v claude >/dev/null 2>& 1; then \
echo "❌ Claude Code not found - required for test generation" ; \
exit 1; \
fi
@CURRENT_ISSUE= $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.number' ) ; \
ISSUE_TITLE = $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.title' ) ; \
ISSUE_BODY = $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.body' ) ; \
echo " 🧪 Adding test to issue # $$ CURRENT_ISSUE workspace " ; \
echo "" ; \
echo " 📋 Issue: $$ ISSUE_TITLE " ; \
echo " 📁 Workspace: $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/ " ; \
echo "" ; \
echo "🤖 Please ask Claude Code to generate a test:" ; \
echo "" ; \
echo " Command: 'Generate a test for the current workspace issue'" ; \
echo "" ; \
echo "📝 Test Requirements:" ; \
echo " - Save test in: $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/tests/ " ; \
echo " - Name format: test_issue_ $$ CURRENT_ISSUE_<scenario>.py " ; \
echo " - Include docstring referencing issue # $$ CURRENT_ISSUE " ; \
echo " - Follow TDD principles (test should fail initially)" ; \
echo " - Review requirements.md and test_plan.md for context" ; \
echo "" ; \
echo "📋 Issue Details:" ; \
echo " Title: $$ ISSUE_TITLE " ; \
echo " Description: $$ ISSUE_BODY " ; \
echo "" ; \
echo "💡 After generation: Use 'make workspace-status' to see all tests"
# Show current workspace status
workspace-status :
@if [ ! -f " $( CURRENT_ISSUE_FILE) " ] ; then \
echo "📋 No active issue workspace" ; \
echo " Use 'make start-issue NUM=X' to begin working on an issue" ; \
exit 0; \
fi
@CURRENT_ISSUE= $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.number' ) ; \
ISSUE_TITLE = $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.title' ) ; \
ISSUE_STATE = $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.state' ) ; \
echo "📋 Active Issue Workspace" ; \
echo "========================" ; \
echo "" ; \
echo " 🎯 Issue # $$ CURRENT_ISSUE: $$ ISSUE_TITLE " ; \
echo " 📊 Status: $$ ISSUE_STATE " ; \
echo " 📁 Workspace: $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/ " ; \
echo "" ; \
if [ -d " $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/tests " ] ; then \
TEST_COUNT = $$ ( find " $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/tests " -name "*.py" | wc -l) ; \
echo " 🧪 Generated Tests ( $$ TEST_COUNT): " ; \
if [ $$ TEST_COUNT -gt 0 ] ; then \
find " $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/tests " -name "*.py" -exec basename { } \; | sed 's/^/ - /' ; \
else \
echo " - No tests generated yet" ; \
fi ; \
echo "" ; \
fi ; \
echo "📋 Workspace Files:" ; \
echo " - requirements.md (review and break down issue)" ; \
echo " - test_plan.md (plan test scenarios)" ; \
echo " - tests/ (generated test files)" ; \
echo "" ; \
echo "💡 Commands:" ; \
echo " - make add-test (generate another test)" ; \
echo " - make finish-issue (complete and move tests to main)"
# Complete issue work (move tests to main and cleanup)
finish-issue :
@if [ ! -f " $( CURRENT_ISSUE_FILE) " ] ; then \
echo "❌ No active issue workspace" ; \
echo " Nothing to finish" ; \
exit 1; \
fi
@CURRENT_ISSUE= $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.number' ) ; \
ISSUE_TITLE = $$ ( cat " $( CURRENT_ISSUE_FILE) " | jq -r '.title' ) ; \
echo " 🏁 Finishing work on issue # $$ CURRENT_ISSUE " ; \
echo "" ; \
if [ -d " $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/tests " ] ; then \
TEST_COUNT = $$ ( find " $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE/tests " -name "*.py" | wc -l) ; \
if [ $$ TEST_COUNT -gt 0 ] ; then \
echo " 📦 Moving $$ TEST_COUNT test(s) to tests/ directory... " ; \
cp $( WORKSPACE_DIR) /issue_$$ CURRENT_ISSUE/tests/*.py tests/ 2>/dev/null || echo " No .py files to move" ; \
echo "✅ Tests moved to main tests/ directory" ; \
else \
echo "⚠️ No tests found in workspace" ; \
fi ; \
fi ; \
echo "🧹 Cleaning up workspace..." ; \
rm -rf " $( WORKSPACE_DIR) /issue_ $$ CURRENT_ISSUE " ; \
rm -f " $( CURRENT_ISSUE_FILE) " ; \
echo " ✅ Issue # $$ CURRENT_ISSUE workspace cleaned up " ; \
echo "" ; \
echo "💡 Next steps:" ; \
echo " - Run 'make test' to verify tests fail (red state)" ; \
echo " - Implement code to make tests pass (green state)" ; \
echo " - Start next issue with 'make start-issue NUM=X'"