# MarkiTect - Advanced Markdown Engine # Makefile for common development tasks .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 # Default target help: @echo "MarkiTect Development Commands" @echo "==============================" @echo "" @echo "Environment Status:" @$(MAKE) --no-print-directory venv-status @echo "" @echo "Setup & Installation:" @echo " setup - Initial project setup (venv + install)" @echo " install - Install package in development mode" @echo " dev - Install with development dependencies" @echo " venv-status - Check if venv is active" @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" @echo "" @echo "Documentation:" @echo " update-digest - Update ProjectStatusDigest.md (requires Claude Code)" @echo " add-diary-entry - Add new entry to ProjectDiary.md (requires Claude Code)" @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" @echo "" @echo "Test-Driven Development:" @echo " test-from-issue NUM=X - Generate test skeleton from issue (requires Claude Code)" @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)" # Python and virtual environment setup PYTHON := python3 VENV := .venv VENV_PYTHON := $(VENV)/bin/python VENV_PIP := $(VENV)/bin/pip # 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 # 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:" $(VENV_PIP) check # 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" # 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" # 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 # Issue workspace configuration WORKSPACE_DIR := .markitect_workspace CURRENT_ISSUE_FILE := $(WORKSPACE_DIR)/current_issue.json # 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" # 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" # 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_.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'"