chore: untrack development directories
- commit
- 314a98fedb22317883c88820cb65cac46cd56f28
- author
- bamen · · 2025-09-09 19:19 UTC
- committer
- bamen · · 2025-09-09 19:56 UTC
- parent
- 565a3d4
- signature
- unsigned
53 files · +0 -8171
D .claude/commands/plan.md +0 -37
| @@ -1,37 +0,0 @@ | |||
| 1 | - | ||
| 2 | - | Plan how to implement the specified feature. | |
| 3 | - | ||
| 4 | - | This is the second step in the Spec-Driven Development lifecycle. | |
| 5 | - | ||
| 6 | - | Given the implementation details provided as an argument, do this: | |
| 7 | - | ||
| 8 | - | 1. Run `scripts/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute. | |
| 9 | - | 2. Read and analyze the feature specification to understand: | |
| 10 | - | - The feature requirements and user stories | |
| 11 | - | - Functional and non-functional requirements | |
| 12 | - | - Success criteria and acceptance criteria | |
| 13 | - | - Any technical constraints or dependencies mentioned | |
| 14 | - | ||
| 15 | - | 3. Read the constitution at `/memory/constitution.md` to understand constitutional requirements. | |
| 16 | - | ||
| 17 | - | 4. Execute the implementation plan template: | |
| 18 | - | - Load `/templates/plan-template.md` (already copied to IMPL_PLAN path) | |
| 19 | - | - Set Input path to FEATURE_SPEC | |
| 20 | - | - Run the Execution Flow (main) function steps 1-10 | |
| 21 | - | - The template is self-contained and executable | |
| 22 | - | - Follow error handling and gate checks as specified | |
| 23 | - | - Let the template guide artifact generation in $SPECS_DIR: | |
| 24 | - | * Phase 0 generates research.md | |
| 25 | - | * Phase 1 generates data-model.md, contracts/, quickstart.md | |
| 26 | - | * Phase 2 generates tasks.md | |
| 27 | - | - Incorporate user-provided details from arguments into Technical Context: $ARGUMENTS | |
| 28 | - | - Update Progress Tracking as you complete each phase | |
| 29 | - | ||
| 30 | - | 5. Verify execution completed: | |
| 31 | - | - Check Progress Tracking shows all phases complete | |
| 32 | - | - Ensure all required artifacts were generated | |
| 33 | - | - Confirm no ERROR states in execution | |
| 34 | - | ||
| 35 | - | 6. Report results with branch name, file paths, and generated artifacts. | |
| 36 | - | ||
| 37 | - | Use absolute paths with the repository root for all file operations to avoid path issues. | |
D .claude/commands/specify.md +0 -13
| @@ -1,13 +0,0 @@ | |||
| 1 | - | ||
| 2 | - | Start a new feature by creating a specification and feature branch. | |
| 3 | - | ||
| 4 | - | This is the first step in the Spec-Driven Development lifecycle. | |
| 5 | - | ||
| 6 | - | Given the feature description provided as an argument, do this: | |
| 7 | - | ||
| 8 | - | 1. Run the script `scripts/create-new-feature.sh --json "$ARGUMENTS"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute. | |
| 9 | - | 2. Load `templates/spec-template.md` to understand required sections. | |
| 10 | - | 3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings. | |
| 11 | - | 4. Report completion with branch name, spec file path, and readiness for the next phase. | |
| 12 | - | ||
| 13 | - | Note: The script creates and checks out the new branch and initializes the spec file before writing. | |
D .claude/commands/tasks.md +0 -59
| @@ -1,59 +0,0 @@ | |||
| 1 | - | ||
| 2 | - | Break down the plan into executable tasks. | |
| 3 | - | ||
| 4 | - | This is the third step in the Spec-Driven Development lifecycle. | |
| 5 | - | ||
| 6 | - | Given the context provided as an argument, do this: | |
| 7 | - | ||
| 8 | - | 1. Run `scripts/check-task-prerequisites.sh --json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. | |
| 9 | - | 2. Load and analyze available design documents: | |
| 10 | - | - Always read plan.md for tech stack and libraries | |
| 11 | - | - IF EXISTS: Read data-model.md for entities | |
| 12 | - | - IF EXISTS: Read contracts/ for API endpoints | |
| 13 | - | - IF EXISTS: Read research.md for technical decisions | |
| 14 | - | - IF EXISTS: Read quickstart.md for test scenarios | |
| 15 | - | ||
| 16 | - | Note: Not all projects have all documents. For example: | |
| 17 | - | - CLI tools might not have contracts/ | |
| 18 | - | - Simple libraries might not need data-model.md | |
| 19 | - | - Generate tasks based on what's available | |
| 20 | - | ||
| 21 | - | 3. Generate tasks following the template: | |
| 22 | - | - Use `/templates/tasks-template.md` as the base | |
| 23 | - | - Replace example tasks with actual tasks based on: | |
| 24 | - | * **Setup tasks**: Project init, dependencies, linting | |
| 25 | - | * **Test tasks [P]**: One per contract, one per integration scenario | |
| 26 | - | * **Core tasks**: One per entity, service, CLI command, endpoint | |
| 27 | - | * **Integration tasks**: DB connections, middleware, logging | |
| 28 | - | * **Polish tasks [P]**: Unit tests, performance, docs | |
| 29 | - | ||
| 30 | - | 4. Task generation rules: | |
| 31 | - | - Each contract file → contract test task marked [P] | |
| 32 | - | - Each entity in data-model → model creation task marked [P] | |
| 33 | - | - Each endpoint → implementation task (not parallel if shared files) | |
| 34 | - | - Each user story → integration test marked [P] | |
| 35 | - | - Different files = can be parallel [P] | |
| 36 | - | - Same file = sequential (no [P]) | |
| 37 | - | ||
| 38 | - | 5. Order tasks by dependencies: | |
| 39 | - | - Setup before everything | |
| 40 | - | - Tests before implementation (TDD) | |
| 41 | - | - Models before services | |
| 42 | - | - Services before endpoints | |
| 43 | - | - Core before integration | |
| 44 | - | - Everything before polish | |
| 45 | - | ||
| 46 | - | 6. Include parallel execution examples: | |
| 47 | - | - Group [P] tasks that can run together | |
| 48 | - | - Show actual Task agent commands | |
| 49 | - | ||
| 50 | - | 7. Create FEATURE_DIR/tasks.md with: | |
| 51 | - | - Correct feature name from implementation plan | |
| 52 | - | - Numbered tasks (T001, T002, etc.) | |
| 53 | - | - Clear file paths for each task | |
| 54 | - | - Dependency notes | |
| 55 | - | - Parallel execution guidance | |
| 56 | - | ||
| 57 | - | Context for task generation: $ARGUMENTS | |
| 58 | - | ||
| 59 | - | The tasks.md should be immediately executable - each task must be specific enough that an LLM can complete it without additional context. | |
D memory/constitution.md +0 -92
| @@ -1,92 +0,0 @@ | |||
| 1 | - | # Dumb Browser Constitution | |
| 2 | - | ||
| 3 | - | ## Core Principles | |
| 4 | - | ||
| 5 | - | ### I. Speed First (NON-NEGOTIABLE) | |
| 6 | - | - Fast startup time is paramount - no feature worth compromising speed | |
| 7 | - | - Single binary with embedded assets - no external dependencies at runtime | |
| 8 | - | - WebKit2GTK for rendering - full compliance without reinventing wheels | |
| 9 | - | - Minimal UI overhead - focus on web content, not chrome | |
| 10 | - | ||
| 11 | - | ### II. Universal Launcher Compatibility | |
| 12 | - | - Support any dmenu-compatible launcher (fuzzel, rofi, tofi, wofi, bemenu) | |
| 13 | - | - Standard stdin/stdout protocol - no launcher-specific integrations | |
| 14 | - | - Clean text-based format for history/suggestions | |
| 15 | - | - Pipeline-friendly: `dumber --dmenu | launcher | dumber --dmenu` | |
| 16 | - | ||
| 17 | - | ### III. Smart URL Handling | |
| 18 | - | - Direct URL detection: `reddit.com` → navigate directly | |
| 19 | - | - Search shortcuts: `g: golang tutorial` → Google search | |
| 20 | - | - History-first search: `reddit` → check history before web search | |
| 21 | - | - No ambiguity - clear rules for input interpretation | |
| 22 | - | ||
| 23 | - | ### IV. Privacy-Conscious History | |
| 24 | - | - Local SQLite database only - no cloud sync | |
| 25 | - | - Configurable retention periods and cleanup | |
| 26 | - | - Visit counting for intelligent suggestions | |
| 27 | - | - User controls data - easy to clear/export | |
| 28 | - | ||
| 29 | - | ### V. Wayland Native | |
| 30 | - | - Built for modern Linux desktop - sway, hyprland, etc. | |
| 31 | - | - WebKit2GTK provides native Wayland integration | |
| 32 | - | - Single instance handling for launcher integration | |
| 33 | - | - Minimal resource usage - no background services | |
| 34 | - | ||
| 35 | - | ## Technical Standards | |
| 36 | - | ||
| 37 | - | ### Stack Requirements | |
| 38 | - | - **Backend**: Go + Wails([v3-alpha](https://github.com/wailsapp/wails/tree/v3.0.0-alpha.28)) + WebKit2GTK + SQLite | |
| 39 | - | - **CLI**: Cobra + Viper for configuration | |
| 40 | - | - **Database**: SQLC for type-safe SQL generation | |
| 41 | - | - **Validation**: Input sanitization libraries ([go-playground/validator](https://github.com/go-playground/validator)) | |
| 42 | - | - **Build**: Single static binary with embedded frontend | |
| 43 | - | - **Dependencies**: WebKit2GTK + GTK3 only (system packages) | |
| 44 | - | ||
| 45 | - | ### Performance Targets | |
| 46 | - | - Startup time: < 500ms from cold start | |
| 47 | - | - Memory usage: < 100MB baseline + WebKit overhead | |
| 48 | - | - History search: < 50ms for 1000+ entries | |
| 49 | - | - Single instance lock: < 10ms response time | |
| 50 | - | ||
| 51 | - | ### Quality Gates | |
| 52 | - | - All database queries must use SQLC generated code | |
| 53 | - | - All user input must be validated and sanitized | |
| 54 | - | - Error handling: proper Go error chains, no panics in user paths | |
| 55 | - | - Logging: structured logging for debugging, minimal in production (Slog for logging in text mode) | |
| 56 | - | ||
| 57 | - | ## Development Workflow | |
| 58 | - | ||
| 59 | - | ### Implementation Order | |
| 60 | - | 1. Core CLI structure (Cobra + Viper) | |
| 61 | - | 2. Database schema + SQLC integration | |
| 62 | - | 3. URL parser + search engine logic with fuzzy finder algorithm | |
| 63 | - | 4. History management (CRUD operations) | |
| 64 | - | 5. Wails browser integration | |
| 65 | - | 6. Dmenu compatibility layer | |
| 66 | - | 7. Configuration system | |
| 67 | - | ||
| 68 | - | ### Testing Requirements | |
| 69 | - | - Unit tests for URL parsing logic | |
| 70 | - | - Integration tests for database operations | |
| 71 | - | - Manual testing with fuzzel integration | |
| 72 | - | - Cross-launcher compatibility verification | |
| 73 | - | ||
| 74 | - | ## Constraints | |
| 75 | - | ||
| 76 | - | ### Simplicity Mandate | |
| 77 | - | - KISS principle - no over-engineering | |
| 78 | - | - Clean Code philosophy throughout | |
| 79 | - | - Single responsibility per module | |
| 80 | - | - Minimal configuration surface | |
| 81 | - | ||
| 82 | - | ### Security Requirements | |
| 83 | - | - No credential storage or session management | |
| 84 | - | - Input sanitization for all user data | |
| 85 | - | - SQL injection prevention via SQLC | |
| 86 | - | - No network requests except web browsing | |
| 87 | - | ||
| 88 | - | ## Governance | |
| 89 | - | ||
| 90 | - | This constitution defines the project's core identity and technical direction. All implementation decisions must align with these principles, prioritizing speed and simplicity above feature richness. | |
| 91 | - | ||
| 92 | - | **Version**: 1.0.0 | **Ratified**: 2025-01-09 | **Last Amended**: 2025-01-09⏎̸ | |
D memory/constitution_update_checklist.md +0 -85
| @@ -1,85 +0,0 @@ | |||
| 1 | - | # Constitution Update Checklist | |
| 2 | - | ||
| 3 | - | When amending the constitution (`/memory/constitution.md`), ensure all dependent documents are updated to maintain consistency. | |
| 4 | - | ||
| 5 | - | ## Templates to Update | |
| 6 | - | ||
| 7 | - | ### When adding/modifying ANY article: | |
| 8 | - | - [ ] `/templates/plan-template.md` - Update Constitution Check section | |
| 9 | - | - [ ] `/templates/spec-template.md` - Update if requirements/scope affected | |
| 10 | - | - [ ] `/templates/tasks-template.md` - Update if new task types needed | |
| 11 | - | - [ ] `/.claude/commands/plan.md` - Update if planning process changes | |
| 12 | - | - [ ] `/.claude/commands/tasks.md` - Update if task generation affected | |
| 13 | - | - [ ] `/CLAUDE.md` - Update runtime development guidelines | |
| 14 | - | ||
| 15 | - | ### Article-specific updates: | |
| 16 | - | ||
| 17 | - | #### Article I (Library-First): | |
| 18 | - | - [ ] Ensure templates emphasize library creation | |
| 19 | - | - [ ] Update CLI command examples | |
| 20 | - | - [ ] Add llms.txt documentation requirements | |
| 21 | - | ||
| 22 | - | #### Article II (CLI Interface): | |
| 23 | - | - [ ] Update CLI flag requirements in templates | |
| 24 | - | - [ ] Add text I/O protocol reminders | |
| 25 | - | ||
| 26 | - | #### Article III (Test-First): | |
| 27 | - | - [ ] Update test order in all templates | |
| 28 | - | - [ ] Emphasize TDD requirements | |
| 29 | - | - [ ] Add test approval gates | |
| 30 | - | ||
| 31 | - | #### Article IV (Integration Testing): | |
| 32 | - | - [ ] List integration test triggers | |
| 33 | - | - [ ] Update test type priorities | |
| 34 | - | - [ ] Add real dependency requirements | |
| 35 | - | ||
| 36 | - | #### Article V (Observability): | |
| 37 | - | - [ ] Add logging requirements to templates | |
| 38 | - | - [ ] Include multi-tier log streaming | |
| 39 | - | - [ ] Update performance monitoring sections | |
| 40 | - | ||
| 41 | - | #### Article VI (Versioning): | |
| 42 | - | - [ ] Add version increment reminders | |
| 43 | - | - [ ] Include breaking change procedures | |
| 44 | - | - [ ] Update migration requirements | |
| 45 | - | ||
| 46 | - | #### Article VII (Simplicity): | |
| 47 | - | - [ ] Update project count limits | |
| 48 | - | - [ ] Add pattern prohibition examples | |
| 49 | - | - [ ] Include YAGNI reminders | |
| 50 | - | ||
| 51 | - | ## Validation Steps | |
| 52 | - | ||
| 53 | - | 1. **Before committing constitution changes:** | |
| 54 | - | - [ ] All templates reference new requirements | |
| 55 | - | - [ ] Examples updated to match new rules | |
| 56 | - | - [ ] No contradictions between documents | |
| 57 | - | ||
| 58 | - | 2. **After updating templates:** | |
| 59 | - | - [ ] Run through a sample implementation plan | |
| 60 | - | - [ ] Verify all constitution requirements addressed | |
| 61 | - | - [ ] Check that templates are self-contained (readable without constitution) | |
| 62 | - | ||
| 63 | - | 3. **Version tracking:** | |
| 64 | - | - [ ] Update constitution version number | |
| 65 | - | - [ ] Note version in template footers | |
| 66 | - | - [ ] Add amendment to constitution history | |
| 67 | - | ||
| 68 | - | ## Common Misses | |
| 69 | - | ||
| 70 | - | Watch for these often-forgotten updates: | |
| 71 | - | - Command documentation (`/commands/*.md`) | |
| 72 | - | - Checklist items in templates | |
| 73 | - | - Example code/commands | |
| 74 | - | - Domain-specific variations (web vs mobile vs CLI) | |
| 75 | - | - Cross-references between documents | |
| 76 | - | ||
| 77 | - | ## Template Sync Status | |
| 78 | - | ||
| 79 | - | Last sync check: 2025-07-16 | |
| 80 | - | - Constitution version: 2.1.1 | |
| 81 | - | - Templates aligned: ❌ (missing versioning, observability details) | |
| 82 | - | ||
| 83 | - | --- | |
| 84 | - | ||
| 85 | - | *This checklist ensures the constitution's principles are consistently applied across all project documentation.*⏎̸ | |
D scripts/check-task-prerequisites.sh +0 -62
| @@ -1,62 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 2 | - | # Check that implementation plan exists and find optional design documents | |
| 3 | - | # Usage: ./check-task-prerequisites.sh [--json] | |
| 4 | - | ||
| 5 | - | set -e | |
| 6 | - | ||
| 7 | - | JSON_MODE=false | |
| 8 | - | for arg in "$@"; do | |
| 9 | - | case "$arg" in | |
| 10 | - | --json) JSON_MODE=true ;; | |
| 11 | - | --help|-h) echo "Usage: $0 [--json]"; exit 0 ;; | |
| 12 | - | esac | |
| 13 | - | done | |
| 14 | - | ||
| 15 | - | # Source common functions | |
| 16 | - | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| 17 | - | source "$SCRIPT_DIR/common.sh" | |
| 18 | - | ||
| 19 | - | # Get all paths | |
| 20 | - | eval $(get_feature_paths) | |
| 21 | - | ||
| 22 | - | # Check if on feature branch | |
| 23 | - | check_feature_branch "$CURRENT_BRANCH" || exit 1 | |
| 24 | - | ||
| 25 | - | # Check if feature directory exists | |
| 26 | - | if [[ ! -d "$FEATURE_DIR" ]]; then | |
| 27 | - | echo "ERROR: Feature directory not found: $FEATURE_DIR" | |
| 28 | - | echo "Run /specify first to create the feature structure." | |
| 29 | - | exit 1 | |
| 30 | - | fi | |
| 31 | - | ||
| 32 | - | # Check for implementation plan (required) | |
| 33 | - | if [[ ! -f "$IMPL_PLAN" ]]; then | |
| 34 | - | echo "ERROR: plan.md not found in $FEATURE_DIR" | |
| 35 | - | echo "Run /plan first to create the plan." | |
| 36 | - | exit 1 | |
| 37 | - | fi | |
| 38 | - | ||
| 39 | - | if $JSON_MODE; then | |
| 40 | - | # Build JSON array of available docs that actually exist | |
| 41 | - | docs=() | |
| 42 | - | [[ -f "$RESEARCH" ]] && docs+=("research.md") | |
| 43 | - | [[ -f "$DATA_MODEL" ]] && docs+=("data-model.md") | |
| 44 | - | ([[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]) && docs+=("contracts/") | |
| 45 | - | [[ -f "$QUICKSTART" ]] && docs+=("quickstart.md") | |
| 46 | - | # join array into JSON | |
| 47 | - | json_docs=$(printf '"%s",' "${docs[@]}") | |
| 48 | - | json_docs="[${json_docs%,}]" | |
| 49 | - | printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs" | |
| 50 | - | else | |
| 51 | - | # List available design documents (optional) | |
| 52 | - | echo "FEATURE_DIR:$FEATURE_DIR" | |
| 53 | - | echo "AVAILABLE_DOCS:" | |
| 54 | - | ||
| 55 | - | # Use common check functions | |
| 56 | - | check_file "$RESEARCH" "research.md" | |
| 57 | - | check_file "$DATA_MODEL" "data-model.md" | |
| 58 | - | check_dir "$CONTRACTS_DIR" "contracts/" | |
| 59 | - | check_file "$QUICKSTART" "quickstart.md" | |
| 60 | - | fi | |
| 61 | - | ||
| 62 | - | # Always succeed - task generation should work with whatever docs are available⏎̸ | |
D scripts/common.sh +0 -77
| @@ -1,77 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 2 | - | # Common functions and variables for all scripts | |
| 3 | - | ||
| 4 | - | # Get repository root | |
| 5 | - | get_repo_root() { | |
| 6 | - | git rev-parse --show-toplevel | |
| 7 | - | } | |
| 8 | - | ||
| 9 | - | # Get current branch | |
| 10 | - | get_current_branch() { | |
| 11 | - | git rev-parse --abbrev-ref HEAD | |
| 12 | - | } | |
| 13 | - | ||
| 14 | - | # Check if current branch is a feature branch | |
| 15 | - | # Returns 0 if valid, 1 if not | |
| 16 | - | check_feature_branch() { | |
| 17 | - | local branch="$1" | |
| 18 | - | if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then | |
| 19 | - | echo "ERROR: Not on a feature branch. Current branch: $branch" | |
| 20 | - | echo "Feature branches should be named like: 001-feature-name" | |
| 21 | - | return 1 | |
| 22 | - | fi | |
| 23 | - | return 0 | |
| 24 | - | } | |
| 25 | - | ||
| 26 | - | # Get feature directory path | |
| 27 | - | get_feature_dir() { | |
| 28 | - | local repo_root="$1" | |
| 29 | - | local branch="$2" | |
| 30 | - | echo "$repo_root/specs/$branch" | |
| 31 | - | } | |
| 32 | - | ||
| 33 | - | # Get all standard paths for a feature | |
| 34 | - | # Usage: eval $(get_feature_paths) | |
| 35 | - | # Sets: REPO_ROOT, CURRENT_BRANCH, FEATURE_DIR, FEATURE_SPEC, IMPL_PLAN, TASKS | |
| 36 | - | get_feature_paths() { | |
| 37 | - | local repo_root=$(get_repo_root) | |
| 38 | - | local current_branch=$(get_current_branch) | |
| 39 | - | local feature_dir=$(get_feature_dir "$repo_root" "$current_branch") | |
| 40 | - | ||
| 41 | - | echo "REPO_ROOT='$repo_root'" | |
| 42 | - | echo "CURRENT_BRANCH='$current_branch'" | |
| 43 | - | echo "FEATURE_DIR='$feature_dir'" | |
| 44 | - | echo "FEATURE_SPEC='$feature_dir/spec.md'" | |
| 45 | - | echo "IMPL_PLAN='$feature_dir/plan.md'" | |
| 46 | - | echo "TASKS='$feature_dir/tasks.md'" | |
| 47 | - | echo "RESEARCH='$feature_dir/research.md'" | |
| 48 | - | echo "DATA_MODEL='$feature_dir/data-model.md'" | |
| 49 | - | echo "QUICKSTART='$feature_dir/quickstart.md'" | |
| 50 | - | echo "CONTRACTS_DIR='$feature_dir/contracts'" | |
| 51 | - | } | |
| 52 | - | ||
| 53 | - | # Check if a file exists and report | |
| 54 | - | check_file() { | |
| 55 | - | local file="$1" | |
| 56 | - | local description="$2" | |
| 57 | - | if [[ -f "$file" ]]; then | |
| 58 | - | echo " ✓ $description" | |
| 59 | - | return 0 | |
| 60 | - | else | |
| 61 | - | echo " ✗ $description" | |
| 62 | - | return 1 | |
| 63 | - | fi | |
| 64 | - | } | |
| 65 | - | ||
| 66 | - | # Check if a directory exists and has files | |
| 67 | - | check_dir() { | |
| 68 | - | local dir="$1" | |
| 69 | - | local description="$2" | |
| 70 | - | if [[ -d "$dir" ]] && [[ -n "$(ls -A "$dir" 2>/dev/null)" ]]; then | |
| 71 | - | echo " ✓ $description" | |
| 72 | - | return 0 | |
| 73 | - | else | |
| 74 | - | echo " ✗ $description" | |
| 75 | - | return 1 | |
| 76 | - | fi | |
| 77 | - | }⏎̸ | |
D scripts/create-new-feature.sh +0 -96
| @@ -1,96 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 2 | - | # Create a new feature with branch, directory structure, and template | |
| 3 | - | # Usage: ./create-new-feature.sh "feature description" | |
| 4 | - | # ./create-new-feature.sh --json "feature description" | |
| 5 | - | ||
| 6 | - | set -e | |
| 7 | - | ||
| 8 | - | JSON_MODE=false | |
| 9 | - | ||
| 10 | - | # Collect non-flag args | |
| 11 | - | ARGS=() | |
| 12 | - | for arg in "$@"; do | |
| 13 | - | case "$arg" in | |
| 14 | - | --json) | |
| 15 | - | JSON_MODE=true | |
| 16 | - | ;; | |
| 17 | - | --help|-h) | |
| 18 | - | echo "Usage: $0 [--json] <feature_description>"; exit 0 ;; | |
| 19 | - | *) | |
| 20 | - | ARGS+=("$arg") ;; | |
| 21 | - | esac | |
| 22 | - | done | |
| 23 | - | ||
| 24 | - | FEATURE_DESCRIPTION="${ARGS[*]}" | |
| 25 | - | if [ -z "$FEATURE_DESCRIPTION" ]; then | |
| 26 | - | echo "Usage: $0 [--json] <feature_description>" >&2 | |
| 27 | - | exit 1 | |
| 28 | - | fi | |
| 29 | - | ||
| 30 | - | # Get repository root | |
| 31 | - | REPO_ROOT=$(git rev-parse --show-toplevel) | |
| 32 | - | SPECS_DIR="$REPO_ROOT/specs" | |
| 33 | - | ||
| 34 | - | # Create specs directory if it doesn't exist | |
| 35 | - | mkdir -p "$SPECS_DIR" | |
| 36 | - | ||
| 37 | - | # Find the highest numbered feature directory | |
| 38 | - | HIGHEST=0 | |
| 39 | - | if [ -d "$SPECS_DIR" ]; then | |
| 40 | - | for dir in "$SPECS_DIR"/*; do | |
| 41 | - | if [ -d "$dir" ]; then | |
| 42 | - | dirname=$(basename "$dir") | |
| 43 | - | number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0") | |
| 44 | - | number=$((10#$number)) | |
| 45 | - | if [ "$number" -gt "$HIGHEST" ]; then | |
| 46 | - | HIGHEST=$number | |
| 47 | - | fi | |
| 48 | - | fi | |
| 49 | - | done | |
| 50 | - | fi | |
| 51 | - | ||
| 52 | - | # Generate next feature number with zero padding | |
| 53 | - | NEXT=$((HIGHEST + 1)) | |
| 54 | - | FEATURE_NUM=$(printf "%03d" "$NEXT") | |
| 55 | - | ||
| 56 | - | # Create branch name from description | |
| 57 | - | BRANCH_NAME=$(echo "$FEATURE_DESCRIPTION" | \ | |
| 58 | - | tr '[:upper:]' '[:lower:]' | \ | |
| 59 | - | sed 's/[^a-z0-9]/-/g' | \ | |
| 60 | - | sed 's/-\+/-/g' | \ | |
| 61 | - | sed 's/^-//' | \ | |
| 62 | - | sed 's/-$//') | |
| 63 | - | ||
| 64 | - | # Extract 2-3 meaningful words | |
| 65 | - | WORDS=$(echo "$BRANCH_NAME" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//') | |
| 66 | - | ||
| 67 | - | # Final branch name | |
| 68 | - | BRANCH_NAME="${FEATURE_NUM}-${WORDS}" | |
| 69 | - | ||
| 70 | - | # Create and switch to new branch | |
| 71 | - | git checkout -b "$BRANCH_NAME" | |
| 72 | - | ||
| 73 | - | # Create feature directory | |
| 74 | - | FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME" | |
| 75 | - | mkdir -p "$FEATURE_DIR" | |
| 76 | - | ||
| 77 | - | # Copy template if it exists | |
| 78 | - | TEMPLATE="$REPO_ROOT/templates/spec-template.md" | |
| 79 | - | SPEC_FILE="$FEATURE_DIR/spec.md" | |
| 80 | - | ||
| 81 | - | if [ -f "$TEMPLATE" ]; then | |
| 82 | - | cp "$TEMPLATE" "$SPEC_FILE" | |
| 83 | - | else | |
| 84 | - | echo "Warning: Template not found at $TEMPLATE" >&2 | |
| 85 | - | touch "$SPEC_FILE" | |
| 86 | - | fi | |
| 87 | - | ||
| 88 | - | if $JSON_MODE; then | |
| 89 | - | printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' \ | |
| 90 | - | "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM" | |
| 91 | - | else | |
| 92 | - | # Output results for the LLM to use (legacy key: value format) | |
| 93 | - | echo "BRANCH_NAME: $BRANCH_NAME" | |
| 94 | - | echo "SPEC_FILE: $SPEC_FILE" | |
| 95 | - | echo "FEATURE_NUM: $FEATURE_NUM" | |
| 96 | - | fi⏎̸ | |
D scripts/generate-types.js +0 -291
| @@ -1,291 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env node | |
| 2 | - | ||
| 3 | - | import { execSync } from 'child_process'; | |
| 4 | - | import { writeFileSync, readFileSync, existsSync, statSync, mkdirSync } from 'fs'; | |
| 5 | - | import { join, dirname } from 'path'; | |
| 6 | - | ||
| 7 | - | /** | |
| 8 | - | * Generate TypeScript types from Go DTOs by parsing Go struct definitions | |
| 9 | - | * Watches for changes in Go files and regenerates automatically | |
| 10 | - | */ | |
| 11 | - | ||
| 12 | - | const GO_MODELS_PATH = 'internal/db/'; | |
| 13 | - | const GO_PARSER_PATH = 'internal/parser/'; | |
| 14 | - | const TS_OUTPUT_PATH = 'frontend/src/types/generated.ts'; | |
| 15 | - | ||
| 16 | - | // Helper function to convert Go types to TypeScript | |
| 17 | - | function convertGoTypeToTS(goType) { | |
| 18 | - | const cleanType = goType.trim().replace(/^\*/, ''); // Remove pointer indicator | |
| 19 | - | ||
| 20 | - | // Handle Go slices: []Type -> Type[] | |
| 21 | - | if (cleanType.startsWith('[]')) { | |
| 22 | - | const elementType = cleanType.slice(2); // Remove [] | |
| 23 | - | return convertGoTypeToTS(elementType) + '[]'; | |
| 24 | - | } | |
| 25 | - | ||
| 26 | - | // Handle sql.Null types | |
| 27 | - | if (cleanType.includes('sql.NullString')) return 'string | null'; | |
| 28 | - | if (cleanType.includes('sql.NullInt64')) return 'number | null'; | |
| 29 | - | if (cleanType.includes('sql.NullTime')) return 'string | null'; | |
| 30 | - | if (cleanType.includes('sql.NullBool')) return 'boolean | null'; | |
| 31 | - | if (cleanType.includes('sql.NullFloat64')) return 'number | null'; | |
| 32 | - | ||
| 33 | - | // Handle Go package prefixes | |
| 34 | - | if (cleanType.includes('*db.History')) return 'History | null'; | |
| 35 | - | if (cleanType.includes('db.History')) return 'History'; | |
| 36 | - | ||
| 37 | - | if (cleanType.includes('time.Time')) return 'string'; // ISO date strings | |
| 38 | - | if (cleanType.includes('time.Duration')) return 'number'; // Nanoseconds | |
| 39 | - | if (cleanType.includes('map[string]interface{}')) return 'Record<string, unknown>'; | |
| 40 | - | if (cleanType.includes('map[string]string')) return 'Record<string, string>'; | |
| 41 | - | if (cleanType.includes('map[string]any')) return 'Record<string, unknown>'; | |
| 42 | - | if (cleanType.includes('string')) return 'string'; | |
| 43 | - | if (cleanType.includes('int') || cleanType.includes('float')) return 'number'; | |
| 44 | - | if (cleanType.includes('bool')) return 'boolean'; | |
| 45 | - | if (cleanType.match(/^[A-Z][a-zA-Z0-9]*$/)) return cleanType; // Custom struct types | |
| 46 | - | ||
| 47 | - | return 'unknown'; // Fallback | |
| 48 | - | } | |
| 49 | - | ||
| 50 | - | // Parse Go struct to extract JSON field names and types | |
| 51 | - | function parseGoStruct(goCode, structName) { | |
| 52 | - | // More sophisticated regex to handle nested braces in type definitions | |
| 53 | - | const structStart = new RegExp(`type\\s+${structName}\\s+struct\\s*{`, 's'); | |
| 54 | - | const startMatch = goCode.match(structStart); | |
| 55 | - | ||
| 56 | - | if (!startMatch) return null; | |
| 57 | - | ||
| 58 | - | // Find the matching closing brace by counting braces | |
| 59 | - | const startIndex = startMatch.index + startMatch[0].length; | |
| 60 | - | let braceCount = 1; | |
| 61 | - | let endIndex = startIndex; | |
| 62 | - | ||
| 63 | - | for (let i = startIndex; i < goCode.length && braceCount > 0; i++) { | |
| 64 | - | if (goCode[i] === '{') braceCount++; | |
| 65 | - | if (goCode[i] === '}') braceCount--; | |
| 66 | - | endIndex = i; | |
| 67 | - | } | |
| 68 | - | ||
| 69 | - | if (braceCount !== 0) return null; // Unmatched braces | |
| 70 | - | ||
| 71 | - | const structContent = goCode.substring(startIndex, endIndex); | |
| 72 | - | const match = [null, structContent]; // Simulate regex match format | |
| 73 | - | ||
| 74 | - | if (!match) return null; | |
| 75 | - | ||
| 76 | - | // First, reconstruct the struct content by merging lines that belong together | |
| 77 | - | const rawContent = match[1]; | |
| 78 | - | const lines = rawContent.split('\n').map(line => line.trim()).filter(line => line && !line.startsWith('//')); | |
| 79 | - | ||
| 80 | - | // Merge multi-line field definitions | |
| 81 | - | const mergedFields = []; | |
| 82 | - | let currentField = ''; | |
| 83 | - | ||
| 84 | - | for (const line of lines) { | |
| 85 | - | // If line starts with a field name (capital letter), it's a new field | |
| 86 | - | if (/^\w+\s+/.test(line)) { | |
| 87 | - | // Save previous field if exists | |
| 88 | - | if (currentField) { | |
| 89 | - | mergedFields.push(currentField); | |
| 90 | - | } | |
| 91 | - | currentField = line; | |
| 92 | - | } else { | |
| 93 | - | // This line continues the previous field | |
| 94 | - | currentField += ' ' + line; | |
| 95 | - | } | |
| 96 | - | } | |
| 97 | - | ||
| 98 | - | // Don't forget the last field | |
| 99 | - | if (currentField) { | |
| 100 | - | mergedFields.push(currentField); | |
| 101 | - | } | |
| 102 | - | ||
| 103 | - | const fields = mergedFields.map(fieldLine => { | |
| 104 | - | // Check for embedded struct (no field name, just type) | |
| 105 | - | const embeddedMatch = fieldLine.match(/^([A-Z][a-zA-Z0-9]*)\s*$/); | |
| 106 | - | if (embeddedMatch) { | |
| 107 | - | const embeddedType = embeddedMatch[1]; | |
| 108 | - | // Return a special marker for embedded structs | |
| 109 | - | return { | |
| 110 | - | embedded: true, | |
| 111 | - | type: embeddedType | |
| 112 | - | }; | |
| 113 | - | } | |
| 114 | - | ||
| 115 | - | // Parse: FieldName type `json:"field_name,omitempty"` | |
| 116 | - | const fieldMatch = fieldLine.match(/^(\w+)\s+([^`]+?)\s*`json:"([^"]+)".*?`/); | |
| 117 | - | if (!fieldMatch) return null; | |
| 118 | - | ||
| 119 | - | const [, fieldName, goType, jsonTag] = fieldMatch; | |
| 120 | - | const jsonField = jsonTag.split(',')[0]; // Remove omitempty, etc. | |
| 121 | - | const isOptional = jsonTag.includes('omitempty') || jsonTag.includes(',omitempty') || goType.trim().startsWith('*'); | |
| 122 | - | ||
| 123 | - | // Convert Go types to TypeScript using helper function | |
| 124 | - | const tsType = convertGoTypeToTS(goType.trim()); | |
| 125 | - | ||
| 126 | - | return { | |
| 127 | - | name: jsonField, | |
| 128 | - | type: tsType, | |
| 129 | - | optional: isOptional | |
| 130 | - | }; | |
| 131 | - | }) | |
| 132 | - | .filter(Boolean); | |
| 133 | - | ||
| 134 | - | // Handle embedded structs by resolving their fields | |
| 135 | - | const resolvedFields = []; | |
| 136 | - | for (const field of fields) { | |
| 137 | - | if (field.embedded) { | |
| 138 | - | // Find the embedded struct and get its fields | |
| 139 | - | const embeddedFields = parseGoStruct(goCode, field.type); | |
| 140 | - | if (embeddedFields) { | |
| 141 | - | resolvedFields.push(...embeddedFields); | |
| 142 | - | } | |
| 143 | - | } else { | |
| 144 | - | resolvedFields.push(field); | |
| 145 | - | } | |
| 146 | - | } | |
| 147 | - | ||
| 148 | - | return resolvedFields; | |
| 149 | - | } | |
| 150 | - | ||
| 151 | - | function generateTSInterface(structName, fields) { | |
| 152 | - | const interfaceFields = fields.map(field => | |
| 153 | - | ` ${field.name}${field.optional ? '?' : ''}: ${field.type};` | |
| 154 | - | ).join('\n'); | |
| 155 | - | ||
| 156 | - | return `export interface ${structName} {\n${interfaceFields}\n}`; | |
| 157 | - | } | |
| 158 | - | ||
| 159 | - | // Function to discover all struct names in Go code | |
| 160 | - | function findAllStructs(goCode) { | |
| 161 | - | const structRegex = /type\s+([A-Z][a-zA-Z0-9]*)\s+struct\s*{/g; | |
| 162 | - | const structs = []; | |
| 163 | - | let match; | |
| 164 | - | ||
| 165 | - | while ((match = structRegex.exec(goCode)) !== null) { | |
| 166 | - | structs.push(match[1]); | |
| 167 | - | } | |
| 168 | - | ||
| 169 | - | return structs; | |
| 170 | - | } | |
| 171 | - | ||
| 172 | - | // Function to find Go enums (const declarations) | |
| 173 | - | function findGoEnums(goCode) { | |
| 174 | - | const enums = []; | |
| 175 | - | ||
| 176 | - | // Look for InputType specifically | |
| 177 | - | if (goCode.includes('type InputType int')) { | |
| 178 | - | // Find the const block that contains InputType values | |
| 179 | - | const constRegex = /const\s*\(\s*([\s\S]*?)\)/; | |
| 180 | - | const matches = goCode.match(constRegex); | |
| 181 | - | ||
| 182 | - | if (matches) { | |
| 183 | - | const constBody = matches[1]; | |
| 184 | - | // Look for any identifier that starts with InputType | |
| 185 | - | const lines = constBody.split('\n'); | |
| 186 | - | const values = []; | |
| 187 | - | let foundInputTypeBlock = false; | |
| 188 | - | ||
| 189 | - | for (const line of lines) { | |
| 190 | - | const trimmedLine = line.trim(); | |
| 191 | - | ||
| 192 | - | // Skip comment lines | |
| 193 | - | if (trimmedLine.startsWith('//')) continue; | |
| 194 | - | ||
| 195 | - | // Check if this line contains an InputType identifier | |
| 196 | - | const identifierMatch = trimmedLine.match(/^\s*(InputType\w+)/); | |
| 197 | - | if (identifierMatch) { | |
| 198 | - | values.push(identifierMatch[1]); | |
| 199 | - | foundInputTypeBlock = true; | |
| 200 | - | } else if (foundInputTypeBlock && trimmedLine === ')') { | |
| 201 | - | // End of const block | |
| 202 | - | break; | |
| 203 | - | } | |
| 204 | - | } | |
| 205 | - | ||
| 206 | - | if (values.length > 0) { | |
| 207 | - | enums.push({ name: 'InputType', values }); | |
| 208 | - | } | |
| 209 | - | } | |
| 210 | - | } | |
| 211 | - | ||
| 212 | - | return enums; | |
| 213 | - | } | |
| 214 | - | ||
| 215 | - | function generateTSEnum(enumName, values) { | |
| 216 | - | const enumValues = values.map((value, index) => ` ${value} = ${index}`).join(',\n'); | |
| 217 | - | return `export enum ${enumName} {\n${enumValues}\n}`; | |
| 218 | - | } | |
| 219 | - | ||
| 220 | - | function generateTypes() { | |
| 221 | - | console.log('🔧 Parsing Go structs and generating TypeScript types...'); | |
| 222 | - | ||
| 223 | - | const sourceFiles = [ | |
| 224 | - | { path: GO_MODELS_PATH, files: ['models.go'] }, | |
| 225 | - | { path: GO_PARSER_PATH, files: ['types.go'] } | |
| 226 | - | ]; | |
| 227 | - | ||
| 228 | - | let combinedTypes = `// GENERATED FROM GO FILES: SEE THE GENERATOR SCRIPT | |
| 229 | - | // Auto-generated TypeScript types from Go structs | |
| 230 | - | // Generated on: ${new Date().toISOString()} | |
| 231 | - | // Generator script: scripts/generate-types.js | |
| 232 | - | // Source files: internal/db/models.go, internal/parser/types.go | |
| 233 | - | // Do not edit manually - run 'node scripts/generate-types.js' to regenerate | |
| 234 | - | ||
| 235 | - | `; | |
| 236 | - | ||
| 237 | - | for (const { path, files } of sourceFiles) { | |
| 238 | - | for (const filename of files) { | |
| 239 | - | const filePath = join(path, filename); | |
| 240 | - | if (!existsSync(filePath)) continue; | |
| 241 | - | ||
| 242 | - | const goCode = readFileSync(filePath, 'utf-8'); | |
| 243 | - | console.log(` 📄 Processing ${filename}...`); | |
| 244 | - | ||
| 245 | - | // Automatically discover all structs in this file | |
| 246 | - | const structsInFile = findAllStructs(goCode); | |
| 247 | - | const enumsInFile = findGoEnums(goCode); | |
| 248 | - | ||
| 249 | - | // Generate enums first | |
| 250 | - | console.log(` Found ${enumsInFile.length} enums in ${filename}`); | |
| 251 | - | for (const enumDef of enumsInFile) { | |
| 252 | - | const tsEnum = generateTSEnum(enumDef.name, enumDef.values); | |
| 253 | - | combinedTypes += tsEnum + '\n\n'; | |
| 254 | - | console.log(` ✓ Generated enum ${enumDef.name} with values: ${enumDef.values.join(', ')}`); | |
| 255 | - | } | |
| 256 | - | ||
| 257 | - | for (const structName of structsInFile) { | |
| 258 | - | const fields = parseGoStruct(goCode, structName); | |
| 259 | - | if (fields && fields.length > 0) { | |
| 260 | - | const tsInterface = generateTSInterface(structName, fields); | |
| 261 | - | combinedTypes += tsInterface + '\n\n'; | |
| 262 | - | console.log(` ✓ Generated ${structName}`); | |
| 263 | - | } | |
| 264 | - | } | |
| 265 | - | } | |
| 266 | - | } | |
| 267 | - | ||
| 268 | - | // Add manual types that are hard to auto-generate | |
| 269 | - | combinedTypes += `// Manual types and enums | |
| 270 | - | export enum InputType { | |
| 271 | - | InputTypeDirectURL = 0, | |
| 272 | - | InputTypeSearchShortcut = 1, | |
| 273 | - | InputTypeHistorySearch = 2, | |
| 274 | - | InputTypeFallbackSearch = 3 | |
| 275 | - | } | |
| 276 | - | ||
| 277 | - | // Type aliases for frontend usage | |
| 278 | - | export type HistoryEntry = History; | |
| 279 | - | export type SearchShortcut = Shortcut; | |
| 280 | - | export type ZoomEntry = ZoomSetting; | |
| 281 | - | `; | |
| 282 | - | ||
| 283 | - | // Ensure output directory exists | |
| 284 | - | mkdirSync(dirname(TS_OUTPUT_PATH), { recursive: true }); | |
| 285 | - | ||
| 286 | - | writeFileSync(TS_OUTPUT_PATH, combinedTypes); | |
| 287 | - | console.log(`✅ TypeScript types generated at: ${TS_OUTPUT_PATH}`); | |
| 288 | - | } | |
| 289 | - | ||
| 290 | - | // One-time generation | |
| 291 | - | generateTypes();⏎̸ | |
D scripts/get-feature-paths.sh +0 -23
| @@ -1,23 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 2 | - | # Get paths for current feature branch without creating anything | |
| 3 | - | # Used by commands that need to find existing feature files | |
| 4 | - | ||
| 5 | - | set -e | |
| 6 | - | ||
| 7 | - | # Source common functions | |
| 8 | - | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| 9 | - | source "$SCRIPT_DIR/common.sh" | |
| 10 | - | ||
| 11 | - | # Get all paths | |
| 12 | - | eval $(get_feature_paths) | |
| 13 | - | ||
| 14 | - | # Check if on feature branch | |
| 15 | - | check_feature_branch "$CURRENT_BRANCH" || exit 1 | |
| 16 | - | ||
| 17 | - | # Output paths (don't create anything) | |
| 18 | - | echo "REPO_ROOT: $REPO_ROOT" | |
| 19 | - | echo "BRANCH: $CURRENT_BRANCH" | |
| 20 | - | echo "FEATURE_DIR: $FEATURE_DIR" | |
| 21 | - | echo "FEATURE_SPEC: $FEATURE_SPEC" | |
| 22 | - | echo "IMPL_PLAN: $IMPL_PLAN" | |
| 23 | - | echo "TASKS: $TASKS"⏎̸ | |
D scripts/setup-plan.sh +0 -44
| @@ -1,44 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 2 | - | # Setup implementation plan structure for current branch | |
| 3 | - | # Returns paths needed for implementation plan generation | |
| 4 | - | # Usage: ./setup-plan.sh [--json] | |
| 5 | - | ||
| 6 | - | set -e | |
| 7 | - | ||
| 8 | - | JSON_MODE=false | |
| 9 | - | for arg in "$@"; do | |
| 10 | - | case "$arg" in | |
| 11 | - | --json) JSON_MODE=true ;; | |
| 12 | - | --help|-h) echo "Usage: $0 [--json]"; exit 0 ;; | |
| 13 | - | esac | |
| 14 | - | done | |
| 15 | - | ||
| 16 | - | # Source common functions | |
| 17 | - | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| 18 | - | source "$SCRIPT_DIR/common.sh" | |
| 19 | - | ||
| 20 | - | # Get all paths | |
| 21 | - | eval $(get_feature_paths) | |
| 22 | - | ||
| 23 | - | # Check if on feature branch | |
| 24 | - | check_feature_branch "$CURRENT_BRANCH" || exit 1 | |
| 25 | - | ||
| 26 | - | # Create specs directory if it doesn't exist | |
| 27 | - | mkdir -p "$FEATURE_DIR" | |
| 28 | - | ||
| 29 | - | # Copy plan template if it exists | |
| 30 | - | TEMPLATE="$REPO_ROOT/templates/plan-template.md" | |
| 31 | - | if [ -f "$TEMPLATE" ]; then | |
| 32 | - | cp "$TEMPLATE" "$IMPL_PLAN" | |
| 33 | - | fi | |
| 34 | - | ||
| 35 | - | if $JSON_MODE; then | |
| 36 | - | printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","SPECS_DIR":"%s","BRANCH":"%s"}\n' \ | |
| 37 | - | "$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" | |
| 38 | - | else | |
| 39 | - | # Output all paths for LLM use | |
| 40 | - | echo "FEATURE_SPEC: $FEATURE_SPEC" | |
| 41 | - | echo "IMPL_PLAN: $IMPL_PLAN" | |
| 42 | - | echo "SPECS_DIR: $FEATURE_DIR" | |
| 43 | - | echo "BRANCH: $CURRENT_BRANCH" | |
| 44 | - | fi⏎̸ | |
D scripts/update-agent-context.sh +0 -234
| @@ -1,234 +0,0 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 2 | - | # Incrementally update agent context files based on new feature plan | |
| 3 | - | # Supports: CLAUDE.md, GEMINI.md, and .github/copilot-instructions.md | |
| 4 | - | # O(1) operation - only reads current context file and new plan.md | |
| 5 | - | ||
| 6 | - | set -e | |
| 7 | - | ||
| 8 | - | REPO_ROOT=$(git rev-parse --show-toplevel) | |
| 9 | - | CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) | |
| 10 | - | FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH" | |
| 11 | - | NEW_PLAN="$FEATURE_DIR/plan.md" | |
| 12 | - | ||
| 13 | - | # Determine which agent context files to update | |
| 14 | - | CLAUDE_FILE="$REPO_ROOT/CLAUDE.md" | |
| 15 | - | GEMINI_FILE="$REPO_ROOT/GEMINI.md" | |
| 16 | - | COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md" | |
| 17 | - | ||
| 18 | - | # Allow override via argument | |
| 19 | - | AGENT_TYPE="$1" | |
| 20 | - | ||
| 21 | - | if [ ! -f "$NEW_PLAN" ]; then | |
| 22 | - | echo "ERROR: No plan.md found at $NEW_PLAN" | |
| 23 | - | exit 1 | |
| 24 | - | fi | |
| 25 | - | ||
| 26 | - | echo "=== Updating agent context files for feature $CURRENT_BRANCH ===" | |
| 27 | - | ||
| 28 | - | # Extract tech from new plan | |
| 29 | - | NEW_LANG=$(grep "^**Language/Version**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Language\/Version**: //' | grep -v "NEEDS CLARIFICATION" || echo "") | |
| 30 | - | NEW_FRAMEWORK=$(grep "^**Primary Dependencies**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Primary Dependencies**: //' | grep -v "NEEDS CLARIFICATION" || echo "") | |
| 31 | - | NEW_TESTING=$(grep "^**Testing**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Testing**: //' | grep -v "NEEDS CLARIFICATION" || echo "") | |
| 32 | - | NEW_DB=$(grep "^**Storage**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Storage**: //' | grep -v "N/A" | grep -v "NEEDS CLARIFICATION" || echo "") | |
| 33 | - | NEW_PROJECT_TYPE=$(grep "^**Project Type**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Project Type**: //' || echo "") | |
| 34 | - | ||
| 35 | - | # Function to update a single agent context file | |
| 36 | - | update_agent_file() { | |
| 37 | - | local target_file="$1" | |
| 38 | - | local agent_name="$2" | |
| 39 | - | ||
| 40 | - | echo "Updating $agent_name context file: $target_file" | |
| 41 | - | ||
| 42 | - | # Create temp file for new context | |
| 43 | - | local temp_file=$(mktemp) | |
| 44 | - | ||
| 45 | - | # If file doesn't exist, create from template | |
| 46 | - | if [ ! -f "$target_file" ]; then | |
| 47 | - | echo "Creating new $agent_name context file..." | |
| 48 | - | ||
| 49 | - | # Check if this is the SDD repo itself | |
| 50 | - | if [ -f "$REPO_ROOT/templates/agent-file-template.md" ]; then | |
| 51 | - | cp "$REPO_ROOT/templates/agent-file-template.md" "$temp_file" | |
| 52 | - | else | |
| 53 | - | echo "ERROR: Template not found at $REPO_ROOT/templates/agent-file-template.md" | |
| 54 | - | return 1 | |
| 55 | - | fi | |
| 56 | - | ||
| 57 | - | # Replace placeholders | |
| 58 | - | sed -i.bak "s/\[PROJECT NAME\]/$(basename $REPO_ROOT)/" "$temp_file" | |
| 59 | - | sed -i.bak "s/\[DATE\]/$(date +%Y-%m-%d)/" "$temp_file" | |
| 60 | - | sed -i.bak "s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/" "$temp_file" | |
| 61 | - | ||
| 62 | - | # Add project structure based on type | |
| 63 | - | if [[ "$NEW_PROJECT_TYPE" == *"web"* ]]; then | |
| 64 | - | sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|backend/\nfrontend/\ntests/|" "$temp_file" | |
| 65 | - | else | |
| 66 | - | sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|src/\ntests/|" "$temp_file" | |
| 67 | - | fi | |
| 68 | - | ||
| 69 | - | # Add minimal commands | |
| 70 | - | if [[ "$NEW_LANG" == *"Python"* ]]; then | |
| 71 | - | COMMANDS="cd src && pytest && ruff check ." | |
| 72 | - | elif [[ "$NEW_LANG" == *"Rust"* ]]; then | |
| 73 | - | COMMANDS="cargo test && cargo clippy" | |
| 74 | - | elif [[ "$NEW_LANG" == *"JavaScript"* ]] || [[ "$NEW_LANG" == *"TypeScript"* ]]; then | |
| 75 | - | COMMANDS="npm test && npm run lint" | |
| 76 | - | else | |
| 77 | - | COMMANDS="# Add commands for $NEW_LANG" | |
| 78 | - | fi | |
| 79 | - | sed -i.bak "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$COMMANDS|" "$temp_file" | |
| 80 | - | ||
| 81 | - | # Add code style | |
| 82 | - | sed -i.bak "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$NEW_LANG: Follow standard conventions|" "$temp_file" | |
| 83 | - | ||
| 84 | - | # Add recent changes | |
| 85 | - | sed -i.bak "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|- $CURRENT_BRANCH: Added $NEW_LANG + $NEW_FRAMEWORK|" "$temp_file" | |
| 86 | - | ||
| 87 | - | rm "$temp_file.bak" | |
| 88 | - | else | |
| 89 | - | echo "Updating existing $agent_name context file..." | |
| 90 | - | ||
| 91 | - | # Extract manual additions | |
| 92 | - | local manual_start=$(grep -n "<!-- MANUAL ADDITIONS START -->" "$target_file" | cut -d: -f1) | |
| 93 | - | local manual_end=$(grep -n "<!-- MANUAL ADDITIONS END -->" "$target_file" | cut -d: -f1) | |
| 94 | - | ||
| 95 | - | if [ ! -z "$manual_start" ] && [ ! -z "$manual_end" ]; then | |
| 96 | - | sed -n "${manual_start},${manual_end}p" "$target_file" > /tmp/manual_additions.txt | |
| 97 | - | fi | |
| 98 | - | ||
| 99 | - | # Parse existing file and create updated version | |
| 100 | - | python3 - << EOF | |
| 101 | - | import re | |
| 102 | - | import sys | |
| 103 | - | from datetime import datetime | |
| 104 | - | ||
| 105 | - | # Read existing file | |
| 106 | - | with open("$target_file", 'r') as f: | |
| 107 | - | content = f.read() | |
| 108 | - | ||
| 109 | - | # Check if new tech already exists | |
| 110 | - | tech_section = re.search(r'## Active Technologies\n(.*?)\n\n', content, re.DOTALL) | |
| 111 | - | if tech_section: | |
| 112 | - | existing_tech = tech_section.group(1) | |
| 113 | - | ||
| 114 | - | # Add new tech if not already present | |
| 115 | - | new_additions = [] | |
| 116 | - | if "$NEW_LANG" and "$NEW_LANG" not in existing_tech: | |
| 117 | - | new_additions.append(f"- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)") | |
| 118 | - | if "$NEW_DB" and "$NEW_DB" not in existing_tech and "$NEW_DB" != "N/A": | |
| 119 | - | new_additions.append(f"- $NEW_DB ($CURRENT_BRANCH)") | |
| 120 | - | ||
| 121 | - | if new_additions: | |
| 122 | - | updated_tech = existing_tech + "\n" + "\n".join(new_additions) | |
| 123 | - | content = content.replace(tech_section.group(0), f"## Active Technologies\n{updated_tech}\n\n") | |
| 124 | - | ||
| 125 | - | # Update project structure if needed | |
| 126 | - | if "$NEW_PROJECT_TYPE" == "web" and "frontend/" not in content: | |
| 127 | - | struct_section = re.search(r'## Project Structure\n\`\`\`\n(.*?)\n\`\`\`', content, re.DOTALL) | |
| 128 | - | if struct_section: | |
| 129 | - | updated_struct = struct_section.group(1) + "\nfrontend/src/ # Web UI" | |
| 130 | - | content = re.sub(r'(## Project Structure\n\`\`\`\n).*?(\n\`\`\`)', | |
| 131 | - | f'\\1{updated_struct}\\2', content, flags=re.DOTALL) | |
| 132 | - | ||
| 133 | - | # Add new commands if language is new | |
| 134 | - | if "$NEW_LANG" and f"# {NEW_LANG}" not in content: | |
| 135 | - | commands_section = re.search(r'## Commands\n\`\`\`bash\n(.*?)\n\`\`\`', content, re.DOTALL) | |
| 136 | - | if not commands_section: | |
| 137 | - | commands_section = re.search(r'## Commands\n(.*?)\n\n', content, re.DOTALL) | |
| 138 | - | ||
| 139 | - | if commands_section: | |
| 140 | - | new_commands = commands_section.group(1) | |
| 141 | - | if "Python" in "$NEW_LANG": | |
| 142 | - | new_commands += "\ncd src && pytest && ruff check ." | |
| 143 | - | elif "Rust" in "$NEW_LANG": | |
| 144 | - | new_commands += "\ncargo test && cargo clippy" | |
| 145 | - | elif "JavaScript" in "$NEW_LANG" or "TypeScript" in "$NEW_LANG": | |
| 146 | - | new_commands += "\nnpm test && npm run lint" | |
| 147 | - | ||
| 148 | - | if "```bash" in content: | |
| 149 | - | content = re.sub(r'(## Commands\n\`\`\`bash\n).*?(\n\`\`\`)', | |
| 150 | - | f'\\1{new_commands}\\2', content, flags=re.DOTALL) | |
| 151 | - | else: | |
| 152 | - | content = re.sub(r'(## Commands\n).*?(\n\n)', | |
| 153 | - | f'\\1{new_commands}\\2', content, flags=re.DOTALL) | |
| 154 | - | ||
| 155 | - | # Update recent changes (keep only last 3) | |
| 156 | - | changes_section = re.search(r'## Recent Changes\n(.*?)(\n\n|$)', content, re.DOTALL) | |
| 157 | - | if changes_section: | |
| 158 | - | changes = changes_section.group(1).strip().split('\n') | |
| 159 | - | changes.insert(0, f"- $CURRENT_BRANCH: Added $NEW_LANG + $NEW_FRAMEWORK") | |
| 160 | - | # Keep only last 3 | |
| 161 | - | changes = changes[:3] | |
| 162 | - | content = re.sub(r'(## Recent Changes\n).*?(\n\n|$)', | |
| 163 | - | f'\\1{chr(10).join(changes)}\\2', content, flags=re.DOTALL) | |
| 164 | - | ||
| 165 | - | # Update date | |
| 166 | - | content = re.sub(r'Last updated: \d{4}-\d{2}-\d{2}', | |
| 167 | - | f'Last updated: {datetime.now().strftime("%Y-%m-%d")}', content) | |
| 168 | - | ||
| 169 | - | # Write to temp file | |
| 170 | - | with open("$temp_file", 'w') as f: | |
| 171 | - | f.write(content) | |
| 172 | - | EOF | |
| 173 | - | ||
| 174 | - | # Restore manual additions if they exist | |
| 175 | - | if [ -f /tmp/manual_additions.txt ]; then | |
| 176 | - | # Remove old manual section from temp file | |
| 177 | - | sed -i.bak '/<!-- MANUAL ADDITIONS START -->/,/<!-- MANUAL ADDITIONS END -->/d' "$temp_file" | |
| 178 | - | # Append manual additions | |
| 179 | - | cat /tmp/manual_additions.txt >> "$temp_file" | |
| 180 | - | rm /tmp/manual_additions.txt "$temp_file.bak" | |
| 181 | - | fi | |
| 182 | - | fi | |
| 183 | - | ||
| 184 | - | # Move temp file to final location | |
| 185 | - | mv "$temp_file" "$target_file" | |
| 186 | - | echo "✅ $agent_name context file updated successfully" | |
| 187 | - | } | |
| 188 | - | ||
| 189 | - | # Update files based on argument or detect existing files | |
| 190 | - | case "$AGENT_TYPE" in | |
| 191 | - | "claude") | |
| 192 | - | update_agent_file "$CLAUDE_FILE" "Claude Code" | |
| 193 | - | ;; | |
| 194 | - | "gemini") | |
| 195 | - | update_agent_file "$GEMINI_FILE" "Gemini CLI" | |
| 196 | - | ;; | |
| 197 | - | "copilot") | |
| 198 | - | update_agent_file "$COPILOT_FILE" "GitHub Copilot" | |
| 199 | - | ;; | |
| 200 | - | "") | |
| 201 | - | # Update all existing files | |
| 202 | - | [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code" | |
| 203 | - | [ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI" | |
| 204 | - | [ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot" | |
| 205 | - | ||
| 206 | - | # If no files exist, create based on current directory or ask user | |
| 207 | - | if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ]; then | |
| 208 | - | echo "No agent context files found. Creating Claude Code context file by default." | |
| 209 | - | update_agent_file "$CLAUDE_FILE" "Claude Code" | |
| 210 | - | fi | |
| 211 | - | ;; | |
| 212 | - | *) | |
| 213 | - | echo "ERROR: Unknown agent type '$AGENT_TYPE'. Use: claude, gemini, copilot, or leave empty for all." | |
| 214 | - | exit 1 | |
| 215 | - | ;; | |
| 216 | - | esac | |
| 217 | - | echo "" | |
| 218 | - | echo "Summary of changes:" | |
| 219 | - | if [ ! -z "$NEW_LANG" ]; then | |
| 220 | - | echo "- Added language: $NEW_LANG" | |
| 221 | - | fi | |
| 222 | - | if [ ! -z "$NEW_FRAMEWORK" ]; then | |
| 223 | - | echo "- Added framework: $NEW_FRAMEWORK" | |
| 224 | - | fi | |
| 225 | - | if [ ! -z "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ]; then | |
| 226 | - | echo "- Added database: $NEW_DB" | |
| 227 | - | fi | |
| 228 | - | ||
| 229 | - | echo "" | |
| 230 | - | echo "Usage: $0 [claude|gemini|copilot]" | |
| 231 | - | echo " - No argument: Update all existing agent context files" | |
| 232 | - | echo " - claude: Update only CLAUDE.md" | |
| 233 | - | echo " - gemini: Update only GEMINI.md" | |
| 234 | - | echo " - copilot: Update only .github/copilot-instructions.md"⏎̸ | |
D specs/001-init-project/contracts/cli-commands.md +0 -245
| @@ -1,245 +0,0 @@ | |||
| 1 | - | # CLI Commands Contract: Project Initialization | |
| 2 | - | ||
| 3 | - | **Date**: 2025-01-09 | |
| 4 | - | **Context**: Command-line interface specification for project initialization | |
| 5 | - | ||
| 6 | - | ## Root Command | |
| 7 | - | ||
| 8 | - | ### `dumber init` | |
| 9 | - | **Purpose**: Initialize the project with all dependencies | |
| 10 | - | ||
| 11 | - | **Syntax**: | |
| 12 | - | ```bash | |
| 13 | - | dumber init [OPTIONS] | |
| 14 | - | ``` | |
| 15 | - | ||
| 16 | - | **Options**: | |
| 17 | - | - `--dry-run`: Show what would be done without executing | |
| 18 | - | - `--force`: Overwrite existing files if present | |
| 19 | - | - `--verbose, -v`: Show detailed progress information | |
| 20 | - | - `--go-version`: Specify Go version requirement (default: auto-detect) | |
| 21 | - | ||
| 22 | - | **Examples**: | |
| 23 | - | ```bash | |
| 24 | - | # Basic initialization | |
| 25 | - | dumber init | |
| 26 | - | ||
| 27 | - | # Preview mode | |
| 28 | - | dumber init --dry-run | |
| 29 | - | ||
| 30 | - | # Force reinitialize existing project | |
| 31 | - | dumber init --force --verbose | |
| 32 | - | ||
| 33 | - | # Specify Go version | |
| 34 | - | dumber init --go-version=1.21 | |
| 35 | - | ``` | |
| 36 | - | ||
| 37 | - | **Exit Codes**: | |
| 38 | - | - `0`: Success | |
| 39 | - | - `1`: General error (invalid arguments, etc.) | |
| 40 | - | - `2`: Dependency installation failed | |
| 41 | - | - `3`: Tool installation failed | |
| 42 | - | - `4`: Project already initialized (without --force) | |
| 43 | - | ||
| 44 | - | **Output Format**: | |
| 45 | - | ``` | |
| 46 | - | ✓ Initializing Go module: dumber | |
| 47 | - | ✓ Installing CLI dependencies: cobra, viper | |
| 48 | - | ✓ Installing database dependencies: sqlite3, sqlc | |
| 49 | - | ✓ Installing validation: go-playground/validator | |
| 50 | - | ✓ Installing testing: testify | |
| 51 | - | ✓ Installing Wails v3-alpha... | |
| 52 | - | ✓ Creating project structure... | |
| 53 | - | ✓ Generating configuration files... | |
| 54 | - | ✓ Verifying installation... | |
| 55 | - | ||
| 56 | - | Project initialized successfully! | |
| 57 | - | ||
| 58 | - | Next steps: | |
| 59 | - | 1. Review generated configs/ | |
| 60 | - | 2. Run: go build ./cmd/dumber | |
| 61 | - | 3. Start development: dumber --help | |
| 62 | - | ``` | |
| 63 | - | ||
| 64 | - | ## Subcommands | |
| 65 | - | ||
| 66 | - | ### `dumber init deps` | |
| 67 | - | **Purpose**: Install only dependencies without project structure | |
| 68 | - | ||
| 69 | - | **Syntax**: | |
| 70 | - | ```bash | |
| 71 | - | dumber init deps [OPTIONS] | |
| 72 | - | ``` | |
| 73 | - | ||
| 74 | - | **Options**: | |
| 75 | - | - `--only`: Install specific dependency category (cli|db|validation|testing|wails) | |
| 76 | - | - `--skip`: Skip specific dependency category | |
| 77 | - | - `--latest`: Use @latest for all dependencies (default) | |
| 78 | - | - `--check`: Verify dependencies without installing | |
| 79 | - | ||
| 80 | - | **Examples**: | |
| 81 | - | ```bash | |
| 82 | - | # Install only CLI dependencies | |
| 83 | - | dumber init deps --only=cli | |
| 84 | - | ||
| 85 | - | # Install everything except Wails | |
| 86 | - | dumber init deps --skip=wails | |
| 87 | - | ||
| 88 | - | # Check current dependency status | |
| 89 | - | dumber init deps --check | |
| 90 | - | ``` | |
| 91 | - | ||
| 92 | - | ### `dumber init structure` | |
| 93 | - | **Purpose**: Create project directory structure only | |
| 94 | - | ||
| 95 | - | **Syntax**: | |
| 96 | - | ```bash | |
| 97 | - | dumber init structure [OPTIONS] | |
| 98 | - | ``` | |
| 99 | - | ||
| 100 | - | **Options**: | |
| 101 | - | - `--template`: Use specific structure template (default|minimal) | |
| 102 | - | - `--preview`: Show directory tree without creating | |
| 103 | - | ||
| 104 | - | **Examples**: | |
| 105 | - | ```bash | |
| 106 | - | # Create full project structure | |
| 107 | - | dumber init structure | |
| 108 | - | ||
| 109 | - | # Preview directory layout | |
| 110 | - | dumber init structure --preview | |
| 111 | - | ||
| 112 | - | # Minimal structure (no example files) | |
| 113 | - | dumber init structure --template=minimal | |
| 114 | - | ``` | |
| 115 | - | ||
| 116 | - | ### `dumber init config` | |
| 117 | - | **Purpose**: Generate configuration files only | |
| 118 | - | ||
| 119 | - | **Syntax**: | |
| 120 | - | ```bash | |
| 121 | - | dumber init config [OPTIONS] | |
| 122 | - | ``` | |
| 123 | - | ||
| 124 | - | **Options**: | |
| 125 | - | - `--type`: Generate specific config (sqlc|wails|all) | |
| 126 | - | - `--overwrite`: Replace existing config files | |
| 127 | - | ||
| 128 | - | **Examples**: | |
| 129 | - | ```bash | |
| 130 | - | # Generate all config files | |
| 131 | - | dumber init config | |
| 132 | - | ||
| 133 | - | # Only SQLC configuration | |
| 134 | - | dumber init config --type=sqlc | |
| 135 | - | ||
| 136 | - | # Replace existing configs | |
| 137 | - | dumber init config --overwrite | |
| 138 | - | ``` | |
| 139 | - | ||
| 140 | - | ## Status and Information Commands | |
| 141 | - | ||
| 142 | - | ### `dumber init status` | |
| 143 | - | **Purpose**: Show initialization status | |
| 144 | - | ||
| 145 | - | **Syntax**: | |
| 146 | - | ```bash | |
| 147 | - | dumber init status [OPTIONS] | |
| 148 | - | ``` | |
| 149 | - | ||
| 150 | - | **Options**: | |
| 151 | - | - `--format`: Output format (text|json|yaml) | |
| 152 | - | - `--detailed`: Show dependency versions and paths | |
| 153 | - | ||
| 154 | - | **Output** (text format): | |
| 155 | - | ``` | |
| 156 | - | Project Status: ✓ Initialized | |
| 157 | - | ||
| 158 | - | Dependencies: | |
| 159 | - | ✓ CLI (cobra v1.8.0, viper v1.18.2) | |
| 160 | - | ✓ Database (sqlite3 v1.14.19, sqlc v1.25.0) | |
| 161 | - | ✓ Validation (validator v10.16.0) | |
| 162 | - | ✓ Testing (testify v1.8.4) | |
| 163 | - | ✗ Wails (not installed) | |
| 164 | - | ||
| 165 | - | Structure: | |
| 166 | - | ✓ cmd/, internal/, migrations/, configs/ | |
| 167 | - | ✗ Missing: tests/integration/ | |
| 168 | - | ||
| 169 | - | Build Status: ✓ Ready (go build succeeds) | |
| 170 | - | ``` | |
| 171 | - | ||
| 172 | - | ### `dumber init verify` | |
| 173 | - | **Purpose**: Verify complete installation | |
| 174 | - | ||
| 175 | - | **Syntax**: | |
| 176 | - | ```bash | |
| 177 | - | dumber init verify [OPTIONS] | |
| 178 | - | ``` | |
| 179 | - | ||
| 180 | - | **Options**: | |
| 181 | - | - `--fix`: Attempt to fix detected issues | |
| 182 | - | - `--report`: Generate detailed verification report | |
| 183 | - | ||
| 184 | - | **Exit Codes**: | |
| 185 | - | - `0`: All verifications passed | |
| 186 | - | - `1`: Some issues detected but not critical | |
| 187 | - | - `2`: Critical issues prevent development | |
| 188 | - | ||
| 189 | - | ## Error Handling | |
| 190 | - | ||
| 191 | - | ### Common Error Scenarios | |
| 192 | - | ||
| 193 | - | **Dependency Installation Failures**: | |
| 194 | - | ```bash | |
| 195 | - | $ dumber init | |
| 196 | - | ✗ Installing database dependencies: sqlite3 | |
| 197 | - | Error: CGO_ENABLED=1 required for sqlite3 | |
| 198 | - | Suggestion: Run 'export CGO_ENABLED=1' and try again | |
| 199 | - | Exit Code: 2 | |
| 200 | - | ``` | |
| 201 | - | ||
| 202 | - | **System Dependency Missing**: | |
| 203 | - | ```bash | |
| 204 | - | $ dumber init | |
| 205 | - | ✗ Installing Wails v3-alpha | |
| 206 | - | Error: libwebkit2gtk-4.0-dev not found | |
| 207 | - | Suggestion: Install with 'sudo apt install libwebkit2gtk-4.0-dev' | |
| 208 | - | Exit Code: 3 | |
| 209 | - | ``` | |
| 210 | - | ||
| 211 | - | **Project Already Exists**: | |
| 212 | - | ```bash | |
| 213 | - | $ dumber init | |
| 214 | - | ✗ Project already initialized | |
| 215 | - | Use --force to reinitialize or run 'dumber init status' | |
| 216 | - | Exit Code: 4 | |
| 217 | - | ``` | |
| 218 | - | ||
| 219 | - | ## Integration with Other Systems | |
| 220 | - | ||
| 221 | - | ### CI/CD Integration | |
| 222 | - | Commands designed for automated environments: | |
| 223 | - | ```bash | |
| 224 | - | # Non-interactive initialization | |
| 225 | - | dumber init --verbose > init.log 2>&1 | |
| 226 | - | ||
| 227 | - | # Verification in CI | |
| 228 | - | dumber init verify --report=ci-report.json | |
| 229 | - | ``` | |
| 230 | - | ||
| 231 | - | ### Development Workflow Integration | |
| 232 | - | ```bash | |
| 233 | - | # Quick setup for new contributors | |
| 234 | - | git clone <repo> && cd <repo> | |
| 235 | - | dumber init | |
| 236 | - | go test ./... | |
| 237 | - | ``` | |
| 238 | - | ||
| 239 | - | ### IDE Integration | |
| 240 | - | Status command provides machine-readable output: | |
| 241 | - | ```bash | |
| 242 | - | dumber init status --format=json | jq '.dependencies.wails.status' | |
| 243 | - | ``` | |
| 244 | - | ||
| 245 | - | This CLI contract supports the initialization phase while providing flexibility for different development scenarios and debugging needs.⏎̸ | |
D specs/001-init-project/contracts/go-module.yaml +0 -152
| @@ -1,152 +0,0 @@ | |||
| 1 | - | # Go Module Contract: Project Dependencies | |
| 2 | - | ||
| 3 | - | # Expected go.mod file structure after initialization | |
| 4 | - | module: dumber | |
| 5 | - | go_version: "1.25" | |
| 6 | - | ||
| 7 | - | # Runtime dependencies (will be installed via go get @latest) | |
| 8 | - | dependencies: | |
| 9 | - | cli: | |
| 10 | - | - import_path: "github.com/spf13/cobra" | |
| 11 | - | purpose: "CLI framework and command handling" | |
| 12 | - | min_version: "v1.8.0" | |
| 13 | - | ||
| 14 | - | - import_path: "github.com/spf13/viper" | |
| 15 | - | purpose: "Configuration management" | |
| 16 | - | min_version: "v1.18.0" | |
| 17 | - | ||
| 18 | - | database: | |
| 19 | - | - import_path: "github.com/ncruces/go-sqlite3" | |
| 20 | - | purpose: "CGO-free SQLite database driver" | |
| 21 | - | min_version: "v0.28.0" | |
| 22 | - | build_tags: [] | |
| 23 | - | requirements: [] | |
| 24 | - | benefits: ["no CGO required", "better performance", "cleaner builds"] | |
| 25 | - | ||
| 26 | - | validation: | |
| 27 | - | - import_path: "github.com/go-playground/validator/v10" | |
| 28 | - | purpose: "Struct validation and input sanitization" | |
| 29 | - | min_version: "v10.16.0" | |
| 30 | - | ||
| 31 | - | testing: | |
| 32 | - | - import_path: "github.com/stretchr/testify" | |
| 33 | - | purpose: "Enhanced testing assertions and mocks" | |
| 34 | - | min_version: "v1.8.4" | |
| 35 | - | scope: "test" | |
| 36 | - | ||
| 37 | - | # Development tools (installed via go install) | |
| 38 | - | tools: | |
| 39 | - | - name: "sqlc" | |
| 40 | - | install_command: "go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest" | |
| 41 | - | purpose: "Generate type-safe Go code from SQL" | |
| 42 | - | version_check: "sqlc version" | |
| 43 | - | ||
| 44 | - | - name: "wails" | |
| 45 | - | install_command: "go install github.com/wailsapp/wails/v3/cmd/wails@v3.0.0-alpha.28" | |
| 46 | - | purpose: "Desktop application framework" | |
| 47 | - | version_check: "wails version" | |
| 48 | - | system_deps: ["libwebkit2gtk-4.0-dev", "libgtk-3-dev"] | |
| 49 | - | ||
| 50 | - | # Expected go.mod content template | |
| 51 | - | go_mod_template: | | |
| 52 | - | module dumber | |
| 53 | - | ||
| 54 | - | go 1.21 | |
| 55 | - | ||
| 56 | - | require ( | |
| 57 | - | github.com/spf13/cobra v1.8.0 | |
| 58 | - | github.com/spf13/viper v1.18.2 | |
| 59 | - | github.com/ncruces/go-sqlite3 v0.28.0 | |
| 60 | - | github.com/go-playground/validator/v10 v10.16.0 | |
| 61 | - | github.com/stretchr/testify v1.8.4 | |
| 62 | - | ) | |
| 63 | - | ||
| 64 | - | # Compatibility matrix | |
| 65 | - | compatibility: | |
| 66 | - | go_version: | |
| 67 | - | minimum: "1.18" # Required for generics | |
| 68 | - | recommended: "1.21" | |
| 69 | - | maximum: "1.22" | |
| 70 | - | ||
| 71 | - | operating_systems: | |
| 72 | - | primary: "linux" | |
| 73 | - | supported: ["linux", "darwin"] | |
| 74 | - | tested: ["archlinux", "ubuntu-22.04"] | |
| 75 | - | ||
| 76 | - | architectures: | |
| 77 | - | primary: "amd64" | |
| 78 | - | supported: ["amd64", "arm64"] | |
| 79 | - | ||
| 80 | - | # Build configuration | |
| 81 | - | build: | |
| 82 | - | tags: | |
| 83 | - | development: ["dev", "debug"] | |
| 84 | - | production: [] | |
| 85 | - | testing: ["test", "integration"] | |
| 86 | - | ||
| 87 | - | environment: | |
| 88 | - | wails_build: | |
| 89 | - | - name: "CGO_ENABLED" | |
| 90 | - | value: "1" | |
| 91 | - | reason: "Required for Wails WebKit2GTK bindings" | |
| 92 | - | cgo_free_development: | |
| 93 | - | - name: "CGO_ENABLED" | |
| 94 | - | value: "0" | |
| 95 | - | reason: "Most development can happen CGO-free (CLI, database, parser)" | |
| 96 | - | ||
| 97 | - | flags: | |
| 98 | - | development: "-race -v" | |
| 99 | - | production: "-ldflags='-s -w'" | |
| 100 | - | ||
| 101 | - | # Verification commands | |
| 102 | - | verification: | |
| 103 | - | module_valid: "go mod verify" | |
| 104 | - | dependencies_resolved: "go mod download" | |
| 105 | - | build_succeeds: "go build ./cmd/dumber" | |
| 106 | - | tests_pass: "go test ./..." | |
| 107 | - | tools_available: | |
| 108 | - | - "sqlc version" | |
| 109 | - | - "wails version" | |
| 110 | - | ||
| 111 | - | # Installation success criteria | |
| 112 | - | success_criteria: | |
| 113 | - | - name: "go.mod exists" | |
| 114 | - | command: "test -f go.mod" | |
| 115 | - | ||
| 116 | - | - name: "module name correct" | |
| 117 | - | command: "grep -q 'module dumber' go.mod" | |
| 118 | - | ||
| 119 | - | - name: "all dependencies resolved" | |
| 120 | - | command: "go mod download && echo 'OK'" | |
| 121 | - | ||
| 122 | - | - name: "build succeeds" | |
| 123 | - | command: "go build -o /tmp/test-build ./cmd/dumber" | |
| 124 | - | cleanup: "rm -f /tmp/test-build" | |
| 125 | - | ||
| 126 | - | - name: "sqlc available" | |
| 127 | - | command: "which sqlc && sqlc version" | |
| 128 | - | ||
| 129 | - | - name: "wails available" | |
| 130 | - | command: "which wails && wails version" | |
| 131 | - | ||
| 132 | - | # Error conditions and solutions | |
| 133 | - | error_handling: | |
| 134 | - | cgo_disabled_for_wails: | |
| 135 | - | error_pattern: "C compiler|CGO_ENABLED.*wails" | |
| 136 | - | solution: "export CGO_ENABLED=1 # Only needed for Wails builds" | |
| 137 | - | documentation: "Wails requires CGO for WebKit2GTK bindings (database layer is CGO-free)" | |
| 138 | - | ||
| 139 | - | missing_webkit: | |
| 140 | - | error_pattern: "webkit2gtk|libwebkit2gtk" | |
| 141 | - | solution: "sudo apt install libwebkit2gtk-4.0-dev libgtk-3-dev" | |
| 142 | - | documentation: "Wails requires WebKit2GTK development headers" | |
| 143 | - | ||
| 144 | - | network_failure: | |
| 145 | - | error_pattern: "dial tcp|connection refused|timeout" | |
| 146 | - | solution: "Check internet connection and proxy settings" | |
| 147 | - | documentation: "Dependency installation requires network access" | |
| 148 | - | ||
| 149 | - | insufficient_space: | |
| 150 | - | error_pattern: "no space left|disk full" | |
| 151 | - | solution: "Free up disk space and try again" | |
| 152 | - | documentation: "Go module cache and tools require ~500MB space"⏎̸ | |
D specs/001-init-project/data-model.md +0 -172
| @@ -1,172 +0,0 @@ | |||
| 1 | - | # Data Model: Project Initialization | |
| 2 | - | ||
| 3 | - | **Date**: 2025-01-09 | |
| 4 | - | **Context**: Data structures for dumber project initialization | |
| 5 | - | ||
| 6 | - | ## Core Entities | |
| 7 | - | ||
| 8 | - | ### 1. Go Module Configuration | |
| 9 | - | **Purpose**: Represents the initialized Go module and its metadata | |
| 10 | - | ||
| 11 | - | **Structure**: | |
| 12 | - | ```go | |
| 13 | - | type ModuleConfig struct { | |
| 14 | - | Name string `validate:"required"` // "dumber" | |
| 15 | - | Version string `validate:"required,semver"` // "v0.1.0" | |
| 16 | - | GoVersion string `validate:"required"` // Go version requirement | |
| 17 | - | Dependencies []Dependency `validate:"dive"` | |
| 18 | - | } | |
| 19 | - | ||
| 20 | - | type Dependency struct { | |
| 21 | - | ImportPath string `validate:"required,uri"` // e.g. "github.com/spf13/cobra" | |
| 22 | - | Version string `validate:"required"` // "@latest" or specific version | |
| 23 | - | Type DependencyType `validate:"required"` // runtime, dev, tool | |
| 24 | - | } | |
| 25 | - | ||
| 26 | - | type DependencyType int | |
| 27 | - | const ( | |
| 28 | - | RuntimeDep DependencyType = iota // Core application dependencies | |
| 29 | - | DevDep // Development/testing tools | |
| 30 | - | ToolDep // CLI tools (sqlc, wails) | |
| 31 | - | ) | |
| 32 | - | ``` | |
| 33 | - | ||
| 34 | - | **Validation Rules**: | |
| 35 | - | - Module name must be valid Go identifier | |
| 36 | - | - Version must follow semantic versioning | |
| 37 | - | - All dependency paths must be valid import paths | |
| 38 | - | - No circular dependencies allowed | |
| 39 | - | ||
| 40 | - | ### 2. Project Structure | |
| 41 | - | **Purpose**: Defines the directory layout and file organization | |
| 42 | - | ||
| 43 | - | **Structure**: | |
| 44 | - | ```go | |
| 45 | - | type ProjectStructure struct { | |
| 46 | - | RootPath string `validate:"required,dir"` | |
| 47 | - | Directories []Directory `validate:"dive"` | |
| 48 | - | ConfigFiles []ConfigFile `validate:"dive"` | |
| 49 | - | InitialFiles []InitialFile `validate:"dive"` | |
| 50 | - | } | |
| 51 | - | ||
| 52 | - | type Directory struct { | |
| 53 | - | Path string `validate:"required"` // relative to root | |
| 54 | - | Purpose string `validate:"required"` // description | |
| 55 | - | Required bool // must be created | |
| 56 | - | } | |
| 57 | - | ||
| 58 | - | type ConfigFile struct { | |
| 59 | - | Path string `validate:"required"` // relative to root | |
| 60 | - | Template string `validate:"required"` // template name | |
| 61 | - | Variables map[string]string // template variables | |
| 62 | - | } | |
| 63 | - | ||
| 64 | - | type InitialFile struct { | |
| 65 | - | Path string `validate:"required"` // relative to root | |
| 66 | - | Content string // file content | |
| 67 | - | Type FileType `validate:"required"` // go, sql, yaml, etc. | |
| 68 | - | } | |
| 69 | - | ``` | |
| 70 | - | ||
| 71 | - | ### 3. Dependency Installation Status | |
| 72 | - | **Purpose**: Tracks installation progress and success/failure states | |
| 73 | - | ||
| 74 | - | **Structure**: | |
| 75 | - | ```go | |
| 76 | - | type InstallationStatus struct { | |
| 77 | - | ModuleName string `validate:"required"` | |
| 78 | - | Dependencies []DependencyStatus `validate:"dive"` | |
| 79 | - | Tools []ToolStatus `validate:"dive"` | |
| 80 | - | Overall StatusType `validate:"required"` | |
| 81 | - | Timestamp time.Time `validate:"required"` | |
| 82 | - | Errors []InstallError | |
| 83 | - | } | |
| 84 | - | ||
| 85 | - | type DependencyStatus struct { | |
| 86 | - | ImportPath string `validate:"required"` | |
| 87 | - | Version string | |
| 88 | - | Status StatusType `validate:"required"` | |
| 89 | - | InstallTime time.Duration // how long to install | |
| 90 | - | Error *InstallError | |
| 91 | - | } | |
| 92 | - | ||
| 93 | - | type ToolStatus struct { | |
| 94 | - | Name string `validate:"required"` // "sqlc", "wails" | |
| 95 | - | Command string `validate:"required"` // installation command | |
| 96 | - | Status StatusType `validate:"required"` | |
| 97 | - | Version string // installed version | |
| 98 | - | Error *InstallError | |
| 99 | - | } | |
| 100 | - | ||
| 101 | - | type StatusType int | |
| 102 | - | const ( | |
| 103 | - | NotStarted StatusType = iota | |
| 104 | - | InProgress | |
| 105 | - | Success | |
| 106 | - | Failed | |
| 107 | - | Skipped | |
| 108 | - | ) | |
| 109 | - | ||
| 110 | - | type InstallError struct { | |
| 111 | - | Message string `validate:"required"` | |
| 112 | - | Code int | |
| 113 | - | Suggestion string // helpful hint for user | |
| 114 | - | } | |
| 115 | - | ``` | |
| 116 | - | ||
| 117 | - | ## State Transitions | |
| 118 | - | ||
| 119 | - | ### Module Initialization Flow | |
| 120 | - | ``` | |
| 121 | - | Empty Directory → Module Init → Dependency Resolution → Tool Installation → Verification → Complete | |
| 122 | - | ↓ ↓ ↓ ↓ | |
| 123 | - | [go.mod] [go.mod updated] [tools available] [build succeeds] | |
| 124 | - | ``` | |
| 125 | - | ||
| 126 | - | ### Dependency Installation States | |
| 127 | - | ``` | |
| 128 | - | NotStarted → InProgress → Success | |
| 129 | - | ↓ | |
| 130 | - | Failed (with retry option) | |
| 131 | - | ``` | |
| 132 | - | ||
| 133 | - | ## Relationships | |
| 134 | - | ||
| 135 | - | 1. **ModuleConfig** contains multiple **Dependencies** | |
| 136 | - | 2. **ProjectStructure** defines where **ConfigFiles** are placed | |
| 137 | - | 3. **InstallationStatus** tracks the progress of **ModuleConfig** setup | |
| 138 | - | 4. Each **Directory** in **ProjectStructure** serves specific **Dependencies** | |
| 139 | - | ||
| 140 | - | ## Validation Constraints | |
| 141 | - | ||
| 142 | - | ### Business Rules | |
| 143 | - | 1. **Module name uniqueness**: No conflicts with existing Go modules in workspace | |
| 144 | - | 2. **Dependency compatibility**: All dependencies must support the same Go version | |
| 145 | - | 3. **Tool availability**: Required tools (sqlc, wails) must be installable | |
| 146 | - | 4. **Directory permissions**: All target directories must be writable | |
| 147 | - | 5. **Disk space**: Adequate space for dependencies and generated files | |
| 148 | - | ||
| 149 | - | ### Technical Constraints | |
| 150 | - | 1. **Go version**: Must support generics (Go 1.18+) | |
| 151 | - | 2. **CGO requirement**: SQLite driver requires CGO_ENABLED=1 | |
| 152 | - | 3. **System dependencies**: Wails requires WebKit2GTK development headers | |
| 153 | - | 4. **Network access**: Dependency download requires internet connectivity | |
| 154 | - | ||
| 155 | - | ## Integration Points | |
| 156 | - | ||
| 157 | - | ### With CLI Commands | |
| 158 | - | - `dumber init` → Creates **ModuleConfig** and **ProjectStructure** | |
| 159 | - | - `dumber deps install` → Updates **InstallationStatus** | |
| 160 | - | - `dumber deps verify` → Validates all **Dependencies** | |
| 161 | - | ||
| 162 | - | ### With Configuration Files | |
| 163 | - | - **go.mod**: Generated from **ModuleConfig** | |
| 164 | - | - **sqlc.yaml**: Generated from database **Dependencies** | |
| 165 | - | - **wails.json**: Generated from Wails **Dependencies** | |
| 166 | - | ||
| 167 | - | ### With Testing Framework | |
| 168 | - | - Integration tests validate each **StatusType** transition | |
| 169 | - | - Contract tests verify **ConfigFile** template generation | |
| 170 | - | - Unit tests cover **Dependency** validation logic | |
| 171 | - | ||
| 172 | - | This data model supports the initialization phase while preparing for the next development phases (CLI implementation, database setup, browser integration).⏎̸ | |
D specs/001-init-project/plan.md +0 -252
| @@ -1,252 +0,0 @@ | |||
| 1 | - | # Implementation Plan: Project Initialization with Dependencies | |
| 2 | - | ||
| 3 | - | **Branch**: `001-init-project` | **Date**: 2025-01-09 | **Spec**: [spec.md](./spec.md) | |
| 4 | - | **Input**: Feature specification from `/home/brice/dev/projects/dumber/specs/001-init-project/spec.md` | |
| 5 | - | ||
| 6 | - | ## Execution Flow (/plan command scope) | |
| 7 | - | ``` | |
| 8 | - | 1. Load feature spec from Input path | |
| 9 | - | → If not found: ERROR "No feature spec at {path}" | |
| 10 | - | 2. Fill Technical Context (scan for NEEDS CLARIFICATION) | |
| 11 | - | → Detect Project Type from context (web=frontend+backend, mobile=app+api) | |
| 12 | - | → Set Structure Decision based on project type | |
| 13 | - | 3. Evaluate Constitution Check section below | |
| 14 | - | → If violations exist: Document in Complexity Tracking | |
| 15 | - | → If no justification possible: ERROR "Simplify approach first" | |
| 16 | - | → Update Progress Tracking: Initial Constitution Check | |
| 17 | - | 4. Execute Phase 0 → research.md | |
| 18 | - | → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns" | |
| 19 | - | 5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI). | |
| 20 | - | 6. Re-evaluate Constitution Check section | |
| 21 | - | → If new violations: Refactor design, return to Phase 1 | |
| 22 | - | → Update Progress Tracking: Post-Design Constitution Check | |
| 23 | - | 7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) | |
| 24 | - | 8. STOP - Ready for /tasks command | |
| 25 | - | ``` | |
| 26 | - | ||
| 27 | - | **IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands: | |
| 28 | - | - Phase 2: /tasks command creates tasks.md | |
| 29 | - | - Phase 3-4: Implementation execution (manual or via tools) | |
| 30 | - | ||
| 31 | - | ## Summary | |
| 32 | - | Initialize a Go project with all required dependencies for the dumber application, following the constitution's technical stack: Go + Wails v3-alpha + WebKit2GTK + SQLite with CLI (Cobra + Viper), database (SQLC), and validation (go-playground/validator) components. Use `go get @latest` for all dependencies. | |
| 33 | - | ||
| 34 | - | ## Technical Context | |
| 35 | - | **User Details**: We need to add all deps using go get @latest | |
| 36 | - | **Language/Version**: Go (latest compatible with Wails v3-alpha) | |
| 37 | - | **Primary Dependencies**: Wails v3-alpha, Cobra, Viper, SQLC, go-playground/validator, SQLite driver | |
| 38 | - | **Storage**: SQLite (local embedded database) | |
| 39 | - | **Testing**: Go standard testing + testify for enhanced assertions | |
| 40 | - | **Target Platform**: Linux Wayland (sway, hyprland) - primary focus | |
| 41 | - | **Project Type**: single (desktop application with CLI + GUI components) | |
| 42 | - | **Performance Goals**: < 500ms startup time, < 100MB baseline memory | |
| 43 | - | **Constraints**: Single binary, WebKit2GTK system dependency only | |
| 44 | - | **Scale/Scope**: Personal productivity tool, local history management (1000+ entries) | |
| 45 | - | ||
| 46 | - | ## Constitution Check | |
| 47 | - | *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | |
| 48 | - | ||
| 49 | - | **Simplicity**: | |
| 50 | - | - Projects: 1 (single desktop app - dumber) | |
| 51 | - | - Using framework directly? YES (Wails, Cobra, Viper directly) | |
| 52 | - | - Single data model? YES (SQLite schema matches Go structs via SQLC) | |
| 53 | - | - Avoiding patterns? YES (no unnecessary abstractions for initialization) | |
| 54 | - | ||
| 55 | - | **Architecture**: | |
| 56 | - | - EVERY feature as library? YES (CLI, parser, database, browser as separate packages) | |
| 57 | - | - Libraries planned: cli (cobra commands), db (sqlc queries), parser (URL handling), browser (Wails integration) | |
| 58 | - | - CLI per library: main CLI with subcommands (--dmenu, history, config) | |
| 59 | - | - Library docs: llms.txt format will be generated post-implementation | |
| 60 | - | ||
| 61 | - | **Testing (NON-NEGOTIABLE)**: | |
| 62 | - | - RED-GREEN-Refactor cycle enforced? YES (tests for module initialization first) | |
| 63 | - | - Git commits show tests before implementation? YES (test dependency resolution before implementation) | |
| 64 | - | - Order: Contract→Integration→E2E→Unit strictly followed? YES | |
| 65 | - | - Real dependencies used? YES (actual Go modules, SQLite DB) | |
| 66 | - | - Integration tests for: module loading, dependency compatibility, build success | |
| 67 | - | - FORBIDDEN: Implementation before test, skipping RED phase | |
| 68 | - | ||
| 69 | - | **Observability**: | |
| 70 | - | - Structured logging included? YES (slog for debugging initialization) | |
| 71 | - | - Frontend logs → backend? N/A for initialization phase | |
| 72 | - | - Error context sufficient? YES (proper error chains for dependency failures) | |
| 73 | - | ||
| 74 | - | **Versioning**: | |
| 75 | - | - Version number assigned? YES (v0.1.0 - initial development) | |
| 76 | - | - BUILD increments on every change? YES (following semantic versioning) | |
| 77 | - | - Breaking changes handled? N/A for initial setup | |
| 78 | - | ||
| 79 | - | ## Project Structure | |
| 80 | - | ||
| 81 | - | ### Documentation (this feature) | |
| 82 | - | ``` | |
| 83 | - | specs/[###-feature]/ | |
| 84 | - | ├── plan.md # This file (/plan command output) | |
| 85 | - | ├── research.md # Phase 0 output (/plan command) | |
| 86 | - | ├── data-model.md # Phase 1 output (/plan command) | |
| 87 | - | ├── quickstart.md # Phase 1 output (/plan command) | |
| 88 | - | ├── contracts/ # Phase 1 output (/plan command) | |
| 89 | - | └── tasks.md # Phase 2 output (/tasks command - NOT created by /plan) | |
| 90 | - | ``` | |
| 91 | - | ||
| 92 | - | ### Source Code (repository root) | |
| 93 | - | ``` | |
| 94 | - | # Option 1: Single project (DEFAULT) | |
| 95 | - | src/ | |
| 96 | - | ├── models/ | |
| 97 | - | ├── services/ | |
| 98 | - | ├── cli/ | |
| 99 | - | └── lib/ | |
| 100 | - | ||
| 101 | - | tests/ | |
| 102 | - | ├── contract/ | |
| 103 | - | ├── integration/ | |
| 104 | - | └── unit/ | |
| 105 | - | ||
| 106 | - | # Option 2: Web application (when "frontend" + "backend" detected) | |
| 107 | - | backend/ | |
| 108 | - | ├── src/ | |
| 109 | - | │ ├── models/ | |
| 110 | - | │ ├── services/ | |
| 111 | - | │ └── api/ | |
| 112 | - | └── tests/ | |
| 113 | - | ||
| 114 | - | frontend/ | |
| 115 | - | ├── src/ | |
| 116 | - | │ ├── components/ | |
| 117 | - | │ ├── pages/ | |
| 118 | - | │ └── services/ | |
| 119 | - | └── tests/ | |
| 120 | - | ||
| 121 | - | # Option 3: Mobile + API (when "iOS/Android" detected) | |
| 122 | - | api/ | |
| 123 | - | └── [same as backend above] | |
| 124 | - | ||
| 125 | - | ios/ or android/ | |
| 126 | - | └── [platform-specific structure] | |
| 127 | - | ``` | |
| 128 | - | ||
| 129 | - | **Structure Decision**: Option 1 - Single project (desktop application with CLI and GUI components) | |
| 130 | - | ||
| 131 | - | ## Phase 0: Outline & Research | |
| 132 | - | 1. **Extract unknowns from Technical Context** above: | |
| 133 | - | - For each NEEDS CLARIFICATION → research task | |
| 134 | - | - For each dependency → best practices task | |
| 135 | - | - For each integration → patterns task | |
| 136 | - | ||
| 137 | - | 2. **Generate and dispatch research agents**: | |
| 138 | - | ``` | |
| 139 | - | For each unknown in Technical Context: | |
| 140 | - | Task: "Research {unknown} for {feature context}" | |
| 141 | - | For each technology choice: | |
| 142 | - | Task: "Find best practices for {tech} in {domain}" | |
| 143 | - | ``` | |
| 144 | - | ||
| 145 | - | 3. **Consolidate findings** in `research.md` using format: | |
| 146 | - | - Decision: [what was chosen] | |
| 147 | - | - Rationale: [why chosen] | |
| 148 | - | - Alternatives considered: [what else evaluated] | |
| 149 | - | ||
| 150 | - | **Output**: research.md with all NEEDS CLARIFICATION resolved | |
| 151 | - | ||
| 152 | - | ## Phase 1: Design & Contracts | |
| 153 | - | *Prerequisites: research.md complete* | |
| 154 | - | ||
| 155 | - | 1. **Extract entities from feature spec** → `data-model.md`: | |
| 156 | - | - Entity name, fields, relationships | |
| 157 | - | - Validation rules from requirements | |
| 158 | - | - State transitions if applicable | |
| 159 | - | ||
| 160 | - | 2. **Generate API contracts** from functional requirements: | |
| 161 | - | - For each user action → endpoint | |
| 162 | - | - Use standard REST/GraphQL patterns | |
| 163 | - | - Output OpenAPI/GraphQL schema to `/contracts/` | |
| 164 | - | ||
| 165 | - | 3. **Generate contract tests** from contracts: | |
| 166 | - | - One test file per endpoint | |
| 167 | - | - Assert request/response schemas | |
| 168 | - | - Tests must fail (no implementation yet) | |
| 169 | - | ||
| 170 | - | 4. **Extract test scenarios** from user stories: | |
| 171 | - | - Each story → integration test scenario | |
| 172 | - | - Quickstart test = story validation steps | |
| 173 | - | ||
| 174 | - | 5. **Update agent file incrementally** (O(1) operation): | |
| 175 | - | - Run `/scripts/update-agent-context.sh [claude|gemini|copilot]` for your AI assistant | |
| 176 | - | - If exists: Add only NEW tech from current plan | |
| 177 | - | - Preserve manual additions between markers | |
| 178 | - | - Update recent changes (keep last 3) | |
| 179 | - | - Keep under 150 lines for token efficiency | |
| 180 | - | - Output to repository root | |
| 181 | - | ||
| 182 | - | **Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file | |
| 183 | - | ||
| 184 | - | ## Phase 2: Task Planning Approach | |
| 185 | - | *This section describes what the /tasks command will do - DO NOT execute during /plan* | |
| 186 | - | ||
| 187 | - | **Task Generation Strategy**: | |
| 188 | - | - Load `/templates/tasks-template.md` as base | |
| 189 | - | - Generate tasks from Phase 1 design docs (contracts, data model, quickstart) | |
| 190 | - | - Prioritize CGO-free components first (faster development cycle) | |
| 191 | - | - Each CLI command contract → contract test + implementation task | |
| 192 | - | - Module initialization → dependency installation tasks | |
| 193 | - | - Project structure → directory creation + config generation tasks | |
| 194 | - | - Integration tests for each success criterion in quickstart | |
| 195 | - | ||
| 196 | - | **Ordering Strategy**: | |
| 197 | - | - TDD order: Tests before implementation | |
| 198 | - | - CGO-free first: CLI, parser, database (can develop with CGO_ENABLED=0) | |
| 199 | - | - Wails integration last: Full application build (requires CGO_ENABLED=1) | |
| 200 | - | - Dependency order: Go module → dependencies → structure → config → verification | |
| 201 | - | - Mark [P] for parallel execution (independent dependency installations) | |
| 202 | - | ||
| 203 | - | **Key Task Categories**: | |
| 204 | - | 1. **Module Setup Tasks**: go mod init, dependency installation | |
| 205 | - | 2. **Structure Tasks**: Directory creation, config file generation | |
| 206 | - | 3. **Verification Tasks**: Build tests, tool availability checks | |
| 207 | - | 4. **Integration Tasks**: Full quickstart validation | |
| 208 | - | ||
| 209 | - | **CGO Optimization**: | |
| 210 | - | - Most tasks can run with CGO_ENABLED=0 for faster iteration | |
| 211 | - | - Only final integration tests require CGO_ENABLED=1 | |
| 212 | - | - Clear separation allows parallel development of CGO-free components | |
| 213 | - | ||
| 214 | - | **Estimated Output**: 15-20 numbered, ordered tasks in tasks.md (streamlined for initialization focus) | |
| 215 | - | ||
| 216 | - | **IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan | |
| 217 | - | ||
| 218 | - | ## Phase 3+: Future Implementation | |
| 219 | - | *These phases are beyond the scope of the /plan command* | |
| 220 | - | ||
| 221 | - | **Phase 3**: Task execution (/tasks command creates tasks.md) | |
| 222 | - | **Phase 4**: Implementation (execute tasks.md following constitutional principles) | |
| 223 | - | **Phase 5**: Validation (run tests, execute quickstart.md, performance validation) | |
| 224 | - | ||
| 225 | - | ## Complexity Tracking | |
| 226 | - | *Fill ONLY if Constitution Check has violations that must be justified* | |
| 227 | - | ||
| 228 | - | | Violation | Why Needed | Simpler Alternative Rejected Because | | |
| 229 | - | |-----------|------------|-------------------------------------| | |
| 230 | - | | [e.g., 4th project] | [current need] | [why 3 projects insufficient] | | |
| 231 | - | | [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] | | |
| 232 | - | ||
| 233 | - | ||
| 234 | - | ## Progress Tracking | |
| 235 | - | *This checklist is updated during execution flow* | |
| 236 | - | ||
| 237 | - | **Phase Status**: | |
| 238 | - | - [x] Phase 0: Research complete (/plan command) | |
| 239 | - | - [x] Phase 1: Design complete (/plan command) | |
| 240 | - | - [x] Phase 2: Task planning complete (/plan command - describe approach only) | |
| 241 | - | - [ ] Phase 3: Tasks generated (/tasks command) | |
| 242 | - | - [ ] Phase 4: Implementation complete | |
| 243 | - | - [ ] Phase 5: Validation passed | |
| 244 | - | ||
| 245 | - | **Gate Status**: | |
| 246 | - | - [x] Initial Constitution Check: PASS | |
| 247 | - | - [x] Post-Design Constitution Check: PASS | |
| 248 | - | - [x] All NEEDS CLARIFICATION resolved | |
| 249 | - | - [x] Complexity deviations documented (none - simplicity maintained) | |
| 250 | - | ||
| 251 | - | --- | |
| 252 | - | *Based on Constitution v2.1.1 - See `/memory/constitution.md`*⏎̸ | |
D specs/001-init-project/quickstart.md +0 -247
| @@ -1,247 +0,0 @@ | |||
| 1 | - | # Quickstart: Project Initialization | |
| 2 | - | ||
| 3 | - | **Goal**: Validate that project initialization works correctly and all dependencies are properly installed. | |
| 4 | - | ||
| 5 | - | ## Prerequisites Verification | |
| 6 | - | ||
| 7 | - | Before running quickstart, verify system requirements: | |
| 8 | - | ||
| 9 | - | ```bash | |
| 10 | - | # Check Go version (1.25+ required) | |
| 11 | - | go version | |
| 12 | - | # Expected: go version go1.25.x linux/amd64 | |
| 13 | - | ||
| 14 | - | # Check system packages for Wails (Arch Linux) | |
| 15 | - | pacman -Q webkit2gtk gtk3 | |
| 16 | - | # Expected: webkit2gtk-4.0 and gtk3 packages listed | |
| 17 | - | ||
| 18 | - | # For Ubuntu/Debian: | |
| 19 | - | # dpkg -l | grep -E "(webkit2gtk|libgtk-3)" | |
| 20 | - | ||
| 21 | - | # Note: CGO only needed for Wails, not for database layer | |
| 22 | - | ``` | |
| 23 | - | ||
| 24 | - | ## Step 1: Project Initialization | |
| 25 | - | ||
| 26 | - | Navigate to project root and initialize: | |
| 27 | - | ||
| 28 | - | ```bash | |
| 29 | - | cd /home/brice/dev/projects/dumber | |
| 30 | - | ||
| 31 | - | # Initialize with verbose output to see progress | |
| 32 | - | dumber init --verbose | |
| 33 | - | ``` | |
| 34 | - | ||
| 35 | - | **Expected Output**: | |
| 36 | - | ``` | |
| 37 | - | ✓ Initializing Go module: dumber | |
| 38 | - | ✓ Installing CLI dependencies: cobra, viper | |
| 39 | - | ✓ Installing database dependencies: ncruces/go-sqlite3, sqlc | |
| 40 | - | ✓ Installing validation: go-playground/validator | |
| 41 | - | ✓ Installing testing: testify | |
| 42 | - | ✓ Installing Wails v3-alpha... (requires CGO) | |
| 43 | - | ✓ Creating project structure... | |
| 44 | - | ✓ Generating configuration files... | |
| 45 | - | ✓ Verifying installation... | |
| 46 | - | ||
| 47 | - | Project initialized successfully! | |
| 48 | - | ||
| 49 | - | Next steps: | |
| 50 | - | 1. Review generated configs/ | |
| 51 | - | 2. Run: go build ./cmd/dumber | |
| 52 | - | 3. Start development: dumber --help | |
| 53 | - | ``` | |
| 54 | - | ||
| 55 | - | ## Step 2: Verify Installation | |
| 56 | - | ||
| 57 | - | Check that all components are correctly installed: | |
| 58 | - | ||
| 59 | - | ```bash | |
| 60 | - | # Verify project status | |
| 61 | - | dumber init status | |
| 62 | - | ||
| 63 | - | # Expected output: | |
| 64 | - | # Project Status: ✓ Initialized | |
| 65 | - | # Dependencies: ✓ All installed | |
| 66 | - | # Structure: ✓ Complete | |
| 67 | - | # Build Status: ✓ Ready | |
| 68 | - | ``` | |
| 69 | - | ||
| 70 | - | Detailed verification: | |
| 71 | - | ||
| 72 | - | ```bash | |
| 73 | - | # Check go.mod exists and is valid | |
| 74 | - | test -f go.mod && echo "✓ go.mod exists" | |
| 75 | - | grep -q "module dumber" go.mod && echo "✓ Module name correct" | |
| 76 | - | ||
| 77 | - | # Verify dependencies are downloadable | |
| 78 | - | go mod download && echo "✓ Dependencies resolved" | |
| 79 | - | ||
| 80 | - | # Check tools are available | |
| 81 | - | sqlc version && echo "✓ SQLC available" | |
| 82 | - | wails version && echo "✓ Wails available" | |
| 83 | - | ``` | |
| 84 | - | ||
| 85 | - | ## Step 3: Test CGO-Free Components | |
| 86 | - | ||
| 87 | - | Most components can be tested without CGO enabled: | |
| 88 | - | ||
| 89 | - | ```bash | |
| 90 | - | # Test CGO-free database layer | |
| 91 | - | export CGO_ENABLED=0 | |
| 92 | - | go build ./internal/db && echo "✓ Database layer builds CGO-free" | |
| 93 | - | go test ./internal/db && echo "✓ Database tests pass CGO-free" | |
| 94 | - | ||
| 95 | - | # Test CLI components | |
| 96 | - | go build ./internal/cli && echo "✓ CLI builds CGO-free" | |
| 97 | - | go test ./internal/cli && echo "✓ CLI tests pass CGO-free" | |
| 98 | - | ||
| 99 | - | # Test URL parser | |
| 100 | - | go build ./internal/parser && echo "✓ Parser builds CGO-free" | |
| 101 | - | go test ./internal/parser && echo "✓ Parser tests pass CGO-free" | |
| 102 | - | ``` | |
| 103 | - | ||
| 104 | - | ## Step 4: Test Wails Integration (CGO Required) | |
| 105 | - | ||
| 106 | - | Test the full application with Wails: | |
| 107 | - | ||
| 108 | - | ```bash | |
| 109 | - | # Enable CGO for Wails | |
| 110 | - | export CGO_ENABLED=1 | |
| 111 | - | ||
| 112 | - | # Test full application build | |
| 113 | - | go build ./cmd/dumber && echo "✓ Full build successful" | |
| 114 | - | ||
| 115 | - | # Clean up test binary | |
| 116 | - | rm -f dumber | |
| 117 | - | ``` | |
| 118 | - | ||
| 119 | - | ## Step 5: Test Project Structure | |
| 120 | - | ||
| 121 | - | Verify the correct directory structure was created: | |
| 122 | - | ||
| 123 | - | ```bash | |
| 124 | - | # Check main directories exist | |
| 125 | - | test -d cmd && echo "✓ cmd/ directory" | |
| 126 | - | test -d internal && echo "✓ internal/ directory" | |
| 127 | - | test -d migrations && echo "✓ migrations/ directory" | |
| 128 | - | test -d configs && echo "✓ configs/ directory" | |
| 129 | - | test -d tests && echo "✓ tests/ directory" | |
| 130 | - | ||
| 131 | - | # Check internal structure | |
| 132 | - | test -d internal/cli && echo "✓ internal/cli/" | |
| 133 | - | test -d internal/db && echo "✓ internal/db/" | |
| 134 | - | test -d internal/parser && echo "✓ internal/parser/" | |
| 135 | - | test -d internal/browser && echo "✓ internal/browser/" | |
| 136 | - | ``` | |
| 137 | - | ||
| 138 | - | ## Step 6: Test Configuration Generation | |
| 139 | - | ||
| 140 | - | Verify that configuration files were generated correctly: | |
| 141 | - | ||
| 142 | - | ```bash | |
| 143 | - | # Check SQLC configuration | |
| 144 | - | test -f configs/sqlc.yaml && echo "✓ SQLC config exists" | |
| 145 | - | sqlc compile -f configs/sqlc.yaml && echo "✓ SQLC config valid" | |
| 146 | - | ||
| 147 | - | # Check basic project files exist (if generated) | |
| 148 | - | test -f cmd/dumber/main.go && echo "✓ Main entry point exists" | |
| 149 | - | ``` | |
| 150 | - | ||
| 151 | - | ## Step 7: Test Module Dependencies | |
| 152 | - | ||
| 153 | - | Verify the updated SQLite dependency: | |
| 154 | - | ||
| 155 | - | ```bash | |
| 156 | - | # Check ncruces/go-sqlite3 is in go.mod (not mattn) | |
| 157 | - | grep -q "github.com/ncruces/go-sqlite3" go.mod && echo "✓ Using CGO-free SQLite driver" | |
| 158 | - | ! grep -q "github.com/mattn/go-sqlite3" go.mod && echo "✓ Not using CGO SQLite driver" | |
| 159 | - | ||
| 160 | - | # Test that database works CGO-free | |
| 161 | - | export CGO_ENABLED=0 | |
| 162 | - | go run -c "import _ 'github.com/ncruces/go-sqlite3'" 2>/dev/null && echo "✓ SQLite driver loads CGO-free" | |
| 163 | - | ``` | |
| 164 | - | ||
| 165 | - | ## Step 8: Validation Tests | |
| 166 | - | ||
| 167 | - | Run tests with different CGO settings: | |
| 168 | - | ||
| 169 | - | ```bash | |
| 170 | - | # Test CGO-free components | |
| 171 | - | export CGO_ENABLED=0 | |
| 172 | - | go test ./internal/cli ./internal/parser ./internal/db && echo "✓ CGO-free tests pass" | |
| 173 | - | ||
| 174 | - | # Test full application with CGO | |
| 175 | - | export CGO_ENABLED=1 | |
| 176 | - | go test ./... && echo "✓ All tests pass with CGO" | |
| 177 | - | ||
| 178 | - | # Test with race detection (requires CGO) | |
| 179 | - | go test -race ./... && echo "✓ No race conditions detected" | |
| 180 | - | ``` | |
| 181 | - | ||
| 182 | - | ## Troubleshooting Common Issues | |
| 183 | - | ||
| 184 | - | ### Issue: Missing WebKit2GTK (Wails only) | |
| 185 | - | **Symptom**: Wails installation fails with webkit error | |
| 186 | - | **Solution** (Arch Linux): | |
| 187 | - | ```bash | |
| 188 | - | sudo pacman -S webkit2gtk gtk3 | |
| 189 | - | dumber init deps --only=wails | |
| 190 | - | ``` | |
| 191 | - | ||
| 192 | - | ### Issue: CGO disabled for Wails | |
| 193 | - | **Symptom**: Wails build fails with CGO error | |
| 194 | - | **Solution**: | |
| 195 | - | ```bash | |
| 196 | - | export CGO_ENABLED=1 | |
| 197 | - | go build ./cmd/dumber | |
| 198 | - | ``` | |
| 199 | - | ||
| 200 | - | ### Issue: Wrong SQLite driver | |
| 201 | - | **Symptom**: CGO errors from mattn/go-sqlite3 | |
| 202 | - | **Verification**: | |
| 203 | - | ```bash | |
| 204 | - | # Should show ncruces, not mattn | |
| 205 | - | grep sqlite3 go.mod | |
| 206 | - | ``` | |
| 207 | - | ||
| 208 | - | ### Issue: Network timeout | |
| 209 | - | **Symptom**: Dependency download timeouts | |
| 210 | - | **Solution**: | |
| 211 | - | ```bash | |
| 212 | - | go env -w GOPROXY=proxy.golang.org,direct | |
| 213 | - | go env -w GOSUMDB=sum.golang.org | |
| 214 | - | dumber init deps | |
| 215 | - | ``` | |
| 216 | - | ||
| 217 | - | ## Success Criteria | |
| 218 | - | ||
| 219 | - | After completing all steps, you should have: | |
| 220 | - | ||
| 221 | - | - ✅ Valid Go module with CGO-free SQLite driver (`ncruces/go-sqlite3`) | |
| 222 | - | - ✅ All CLI, parser, database components buildable with `CGO_ENABLED=0` | |
| 223 | - | - ✅ Full application buildable with `CGO_ENABLED=1` (for Wails) | |
| 224 | - | - ✅ Project directory structure created per constitution | |
| 225 | - | - ✅ Configuration files generated and valid | |
| 226 | - | - ✅ All tools (sqlc, wails) available and functional | |
| 227 | - | - ✅ Clean separation: CGO only needed for browser layer | |
| 228 | - | ||
| 229 | - | ## Development Workflow Benefits | |
| 230 | - | ||
| 231 | - | This CGO strategy provides several advantages: | |
| 232 | - | ||
| 233 | - | 1. **Fast development cycle**: Most development can happen CGO-free | |
| 234 | - | 2. **Better testing**: Database and CLI logic testable without CGO setup | |
| 235 | - | 3. **Cleaner builds**: Only final integration requires CGO | |
| 236 | - | 4. **Better performance**: `ncruces/go-sqlite3` is faster than `mattn/go-sqlite3` | |
| 237 | - | ||
| 238 | - | ## Next Steps | |
| 239 | - | ||
| 240 | - | After successful initialization: | |
| 241 | - | ||
| 242 | - | 1. **Start with CGO-free components**: CLI structure, URL parsing, database schema | |
| 243 | - | 2. **Test incrementally**: Each component works independently | |
| 244 | - | 3. **Integrate with Wails last**: Final step requires CGO for browser integration | |
| 245 | - | 4. **Development workflow**: Most work can be done with `CGO_ENABLED=0` | |
| 246 | - | ||
| 247 | - | The project is now ready for feature development with optimal CGO separation.⏎̸ | |
D specs/001-init-project/research.md +0 -176
| @@ -1,176 +0,0 @@ | |||
| 1 | - | # Research: Project Initialization Dependencies | |
| 2 | - | ||
| 3 | - | **Date**: 2025-01-09 | |
| 4 | - | **Context**: Resolve technical unknowns for dumber project initialization | |
| 5 | - | ||
| 6 | - | ## Research Questions Resolved | |
| 7 | - | ||
| 8 | - | ### 1. Go Module Initialization | |
| 9 | - | **Decision**: Use `go mod init dumber` | |
| 10 | - | **Rationale**: | |
| 11 | - | - Simple module name matching the binary name | |
| 12 | - | - Local development focus (no public import path needed) | |
| 13 | - | - Follows Go module naming conventions | |
| 14 | - | ||
| 15 | - | **Alternatives considered**: | |
| 16 | - | - `github.com/user/dumber` - rejected (unnecessary complexity for local tool) | |
| 17 | - | - `dumber/v1` - rejected (premature versioning) | |
| 18 | - | ||
| 19 | - | ### 2. Wails v3-Alpha Compatibility | |
| 20 | - | **Decision**: Use Wails v3.0.0-alpha.28 (latest available) | |
| 21 | - | **Rationale**: | |
| 22 | - | - Constitution specifically requires v3-alpha | |
| 23 | - | - Alpha version provides newest WebKit2GTK integration | |
| 24 | - | - Active development branch with Wayland improvements | |
| 25 | - | - Breaking changes acceptable for new project | |
| 26 | - | ||
| 27 | - | **Alternatives considered**: | |
| 28 | - | - Wails v2 stable - rejected (constitution mandates v3-alpha) | |
| 29 | - | - Wait for v3 stable - rejected (delays development unnecessarily) | |
| 30 | - | ||
| 31 | - | **Integration approach**: | |
| 32 | - | ```bash | |
| 33 | - | go install github.com/wailsapp/wails/v3/cmd/wails@v3.0.0-alpha.28 | |
| 34 | - | ``` | |
| 35 | - | ||
| 36 | - | ### 3. CLI Framework Selection | |
| 37 | - | **Decision**: Cobra v1.8+ with Viper v1.18+ | |
| 38 | - | **Rationale**: | |
| 39 | - | - Constitution requirement: "Cobra + Viper for configuration" | |
| 40 | - | - Mature, stable libraries with excellent Go ecosystem integration | |
| 41 | - | - Perfect for dmenu/rofi integration via stdin/stdout | |
| 42 | - | - Built-in flag parsing and configuration management | |
| 43 | - | ||
| 44 | - | **Key packages**: | |
| 45 | - | - `github.com/spf13/cobra@latest` | |
| 46 | - | - `github.com/spf13/viper@latest` | |
| 47 | - | ||
| 48 | - | ### 4. Database Stack | |
| 49 | - | **Decision**: SQLite with ncruces/go-sqlite3 (CGO-free) + SQLC v1.25+ | |
| 50 | - | **Rationale**: | |
| 51 | - | - Constitution requirement: "SQLite + SQLC for type-safe SQL" | |
| 52 | - | - `github.com/ncruces/go-sqlite3` is CGO-free (better performance, fewer build issues) | |
| 53 | - | - Only Wails needs CGO, not database layer - cleaner separation | |
| 54 | - | - SQLC generates type-safe Go code from SQL schemas | |
| 55 | - | - Perfect for local history storage | |
| 56 | - | ||
| 57 | - | **Key packages**: | |
| 58 | - | - `github.com/ncruces/go-sqlite3@latest` (CGO-free SQLite driver) | |
| 59 | - | - Install SQLC CLI tool: `go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest` | |
| 60 | - | ||
| 61 | - | **Alternatives considered**: | |
| 62 | - | - `github.com/mattn/go-sqlite3` - rejected (requires CGO unnecessarily) | |
| 63 | - | - Pure Go implementations - rejected (ncruces is the modern standard) | |
| 64 | - | ||
| 65 | - | ### 5. Input Validation | |
| 66 | - | **Decision**: go-playground/validator v10.16+ | |
| 67 | - | **Rationale**: | |
| 68 | - | - Constitution requirement | |
| 69 | - | - Industry standard for Go struct validation | |
| 70 | - | - URL validation capabilities for browser input | |
| 71 | - | - Tag-based validation (clean code) | |
| 72 | - | ||
| 73 | - | **Key package**: | |
| 74 | - | - `github.com/go-playground/validator/v10@latest` | |
| 75 | - | ||
| 76 | - | ### 6. Testing Framework | |
| 77 | - | **Decision**: Standard Go testing + testify v1.8+ | |
| 78 | - | **Rationale**: | |
| 79 | - | - Standard library first approach (constitution: simplicity) | |
| 80 | - | - testify for better assertions and test organization | |
| 81 | - | - No need for heavyweight testing frameworks | |
| 82 | - | ||
| 83 | - | **Key package**: | |
| 84 | - | - `github.com/stretchr/testify@latest` | |
| 85 | - | ||
| 86 | - | ### 7. Project Directory Structure | |
| 87 | - | **Decision**: Follow constitution implementation order | |
| 88 | - | ``` | |
| 89 | - | / | |
| 90 | - | ├── cmd/ # CLI entry point | |
| 91 | - | ├── internal/ | |
| 92 | - | │ ├── cli/ # Cobra commands | |
| 93 | - | │ ├── db/ # SQLC generated code + migrations | |
| 94 | - | │ ├── parser/ # URL parsing logic | |
| 95 | - | │ └── browser/ # Wails integration | |
| 96 | - | ├── migrations/ # SQL schema files | |
| 97 | - | ├── configs/ # Configuration files (SQLC, Wails) | |
| 98 | - | └── tests/ # Integration tests | |
| 99 | - | ``` | |
| 100 | - | ||
| 101 | - | **Rationale**: | |
| 102 | - | - `internal/` prevents external imports (Go convention) | |
| 103 | - | - Matches constitution implementation order | |
| 104 | - | - Separates concerns clearly | |
| 105 | - | - Easy to test individual components | |
| 106 | - | ||
| 107 | - | ### 8. Build Configuration | |
| 108 | - | **Decision**: Standard Go build with Wails embedding | |
| 109 | - | **Rationale**: | |
| 110 | - | - Single binary requirement from constitution | |
| 111 | - | - Wails handles frontend asset embedding | |
| 112 | - | - Standard go build for CLI-only functionality | |
| 113 | - | ||
| 114 | - | ## Dependency Installation Order | |
| 115 | - | ||
| 116 | - | Based on research, the installation sequence should be: | |
| 117 | - | ||
| 118 | - | 1. **Initialize Go module** | |
| 119 | - | ```bash | |
| 120 | - | go mod init dumber | |
| 121 | - | ``` | |
| 122 | - | ||
| 123 | - | 2. **Install CLI dependencies** | |
| 124 | - | ```bash | |
| 125 | - | go get github.com/spf13/cobra@latest | |
| 126 | - | go get github.com/spf13/viper@latest | |
| 127 | - | ``` | |
| 128 | - | ||
| 129 | - | 3. **Install database dependencies** | |
| 130 | - | ```bash | |
| 131 | - | go get github.com/ncruces/go-sqlite3@latest | |
| 132 | - | go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest | |
| 133 | - | ``` | |
| 134 | - | ||
| 135 | - | 4. **Install validation** | |
| 136 | - | ```bash | |
| 137 | - | go get github.com/go-playground/validator/v10@latest | |
| 138 | - | ``` | |
| 139 | - | ||
| 140 | - | 5. **Install testing tools** | |
| 141 | - | ```bash | |
| 142 | - | go get github.com/stretchr/testify@latest | |
| 143 | - | ``` | |
| 144 | - | ||
| 145 | - | 6. **Install Wails (last - most complex)** | |
| 146 | - | ```bash | |
| 147 | - | go install github.com/wailsapp/wails/v3/cmd/wails@v3.0.0-alpha.28 | |
| 148 | - | # Wails will handle its own module dependencies during init | |
| 149 | - | ``` | |
| 150 | - | ||
| 151 | - | ## Risk Assessment | |
| 152 | - | ||
| 153 | - | **Low Risk**: | |
| 154 | - | - Standard Go dependencies (Cobra, Viper, SQLite) | |
| 155 | - | - Well-established patterns | |
| 156 | - | ||
| 157 | - | **Medium Risk**: | |
| 158 | - | - Wails v3-alpha stability (alpha software) | |
| 159 | - | - WebKit2GTK system dependency availability | |
| 160 | - | - CGO requirement for Wails (but not for database layer) | |
| 161 | - | ||
| 162 | - | **Mitigation**: | |
| 163 | - | - Test Wails installation immediately after dependency setup | |
| 164 | - | - Verify WebKit2GTK availability in integration tests | |
| 165 | - | - Document CGO requirement clearly (only for final Wails build) | |
| 166 | - | - Database layer can be developed/tested CGO-free independently | |
| 167 | - | ||
| 168 | - | ## Next Phase Requirements | |
| 169 | - | ||
| 170 | - | All technical unknowns resolved. Phase 1 can proceed with: | |
| 171 | - | - Data model design (SQLite schema) | |
| 172 | - | - Contract definitions (CLI commands) | |
| 173 | - | - Integration test scenarios | |
| 174 | - | - Configuration file generation | |
| 175 | - | ||
| 176 | - | **Status**: ✅ Complete - All NEEDS CLARIFICATION items resolved⏎̸ | |
D specs/001-init-project/spec.md +0 -103
| @@ -1,103 +0,0 @@ | |||
| 1 | - | # Feature Specification: Project Initialization with Dependencies | |
| 2 | - | ||
| 3 | - | **Feature Branch**: `001-init-project` | |
| 4 | - | **Created**: 2025-01-09 | |
| 5 | - | **Status**: Draft | |
| 6 | - | **Input**: User description: "Lets init the project adding all deps" | |
| 7 | - | ||
| 8 | - | ## Execution Flow (main) | |
| 9 | - | ``` | |
| 10 | - | 1. Parse user description from Input | |
| 11 | - | → "Initialize project with all required dependencies" | |
| 12 | - | 2. Extract key concepts from description | |
| 13 | - | → Actors: developer, build system | |
| 14 | - | → Actions: initialize, add dependencies, configure | |
| 15 | - | → Data: project structure, dependency management | |
| 16 | - | → Constraints: follow constitution requirements | |
| 17 | - | 3. For each unclear aspect: | |
| 18 | - | → No major ambiguities - project structure defined in constitution | |
| 19 | - | 4. Fill User Scenarios & Testing section | |
| 20 | - | → Clear flow: developer initializes → dependencies installed → project ready | |
| 21 | - | 5. Generate Functional Requirements | |
| 22 | - | → Each requirement testable through build/run verification | |
| 23 | - | 6. Identify Key Entities: Go modules, dependencies, configuration files | |
| 24 | - | 7. Run Review Checklist | |
| 25 | - | → No [NEEDS CLARIFICATION] markers needed | |
| 26 | - | → No implementation details beyond necessary project structure | |
| 27 | - | 8. Return: SUCCESS (spec ready for planning) | |
| 28 | - | ``` | |
| 29 | - | ||
| 30 | - | --- | |
| 31 | - | ||
| 32 | - | ## ⚡ Quick Guidelines | |
| 33 | - | - ✅ Focus on WHAT users need and WHY | |
| 34 | - | - ❌ Avoid HOW to implement (no tech stack, APIs, code structure) | |
| 35 | - | - 👥 Written for business stakeholders, not developers | |
| 36 | - | ||
| 37 | - | --- | |
| 38 | - | ||
| 39 | - | ## User Scenarios & Testing *(mandatory)* | |
| 40 | - | ||
| 41 | - | ### Primary User Story | |
| 42 | - | As a developer starting work on the dumber project, I need a properly initialized Go project with all required dependencies installed so that I can begin implementing features according to the project constitution without manual setup overhead. | |
| 43 | - | ||
| 44 | - | ### Acceptance Scenarios | |
| 45 | - | 1. **Given** an empty project directory, **When** project initialization is complete, **Then** the project has a valid Go module structure | |
| 46 | - | 2. **Given** the initialized project, **When** checking dependencies, **Then** all required packages from the constitution are available | |
| 47 | - | 3. **Given** the initialized project, **When** running basic build commands, **Then** no dependency resolution errors occur | |
| 48 | - | 4. **Given** the project structure, **When** examining the layout, **Then** it follows the planned architecture (CLI, database, browser components) | |
| 49 | - | ||
| 50 | - | ### Edge Cases | |
| 51 | - | - What happens when Go version is incompatible with selected dependencies? | |
| 52 | - | - How does system handle network failures during dependency installation? | |
| 53 | - | - What occurs if required system packages (WebKit2GTK) are missing? | |
| 54 | - | ||
| 55 | - | ## Requirements *(mandatory)* | |
| 56 | - | ||
| 57 | - | ### Functional Requirements | |
| 58 | - | - **FR-001**: System MUST initialize a valid Go module with appropriate module path | |
| 59 | - | - **FR-002**: System MUST install CLI framework dependencies (Cobra, Viper) | |
| 60 | - | - **FR-003**: System MUST install database dependencies (SQLite driver, SQLC tooling) | |
| 61 | - | - **FR-004**: System MUST install validation dependencies (go-playground/validator) | |
| 62 | - | - **FR-005**: System MUST install Wails v3-alpha framework for browser integration | |
| 63 | - | - **FR-006**: System MUST create basic project directory structure aligned with planned architecture | |
| 64 | - | - **FR-007**: System MUST configure SQLC for type-safe database code generation | |
| 65 | - | - **FR-008**: System MUST verify all dependencies are compatible and buildable | |
| 66 | - | - **FR-009**: System MUST create configuration files needed for the development workflow | |
| 67 | - | ||
| 68 | - | ### Key Entities | |
| 69 | - | - **Go Module**: The main project module with proper versioning and dependency management | |
| 70 | - | - **Configuration Files**: SQLC config, Wails config, and other tool configurations | |
| 71 | - | - **Project Structure**: Directory layout supporting CLI, database, and browser components | |
| 72 | - | - **Dependencies**: External packages required per the constitution (Cobra, Viper, SQLite, SQLC, Wails, validator) | |
| 73 | - | ||
| 74 | - | --- | |
| 75 | - | ||
| 76 | - | ## Review & Acceptance Checklist | |
| 77 | - | ||
| 78 | - | ### Content Quality | |
| 79 | - | - [x] No implementation details (languages, frameworks, APIs) | |
| 80 | - | - [x] Focused on user value and business needs | |
| 81 | - | - [x] Written for non-technical stakeholders | |
| 82 | - | - [x] All mandatory sections completed | |
| 83 | - | ||
| 84 | - | ### Requirement Completeness | |
| 85 | - | - [x] No [NEEDS CLARIFICATION] markers remain | |
| 86 | - | - [x] Requirements are testable and unambiguous | |
| 87 | - | - [x] Success criteria are measurable | |
| 88 | - | - [x] Scope is clearly bounded | |
| 89 | - | - [x] Dependencies and assumptions identified | |
| 90 | - | ||
| 91 | - | --- | |
| 92 | - | ||
| 93 | - | ## Execution Status | |
| 94 | - | ||
| 95 | - | - [x] User description parsed | |
| 96 | - | - [x] Key concepts extracted | |
| 97 | - | - [x] Ambiguities marked | |
| 98 | - | - [x] User scenarios defined | |
| 99 | - | - [x] Requirements generated | |
| 100 | - | - [x] Entities identified | |
| 101 | - | - [x] Review checklist passed | |
| 102 | - | ||
| 103 | - | ---⏎̸ | |
D specs/001-init-project/tasks.md +0 -170
| @@ -1,170 +0,0 @@ | |||
| 1 | - | # Tasks: Project Initialization with Dependencies | |
| 2 | - | ||
| 3 | - | **Input**: Design documents from `/home/brice/dev/projects/dumber/specs/001-init-project/` | |
| 4 | - | **Prerequisites**: plan.md, research.md, data-model.md, contracts/ | |
| 5 | - | ||
| 6 | - | ## Execution Flow (main) | |
| 7 | - | Project initialization requires setting up Go module, installing dependencies with `go get @latest`, creating directory structure, and verifying installation. Tasks follow TDD principles with contract tests before implementation. | |
| 8 | - | ||
| 9 | - | ## Format: `[ID] [P?] Description` | |
| 10 | - | - **[P]**: Can run in parallel (different files, no dependencies) | |
| 11 | - | - Include exact file paths in descriptions | |
| 12 | - | ||
| 13 | - | ## Path Conventions | |
| 14 | - | Single project structure: `cmd/`, `internal/`, `tests/` at repository root per constitution | |
| 15 | - | ||
| 16 | - | ## Phase 3.1: Setup and Structure | |
| 17 | - | ||
| 18 | - | - [ ] T001 Initialize Go module with `go mod init dumber` in project root | |
| 19 | - | - [ ] T002 Create project directory structure: `cmd/dumber/`, `internal/{cli,db,parser,browser}/`, `migrations/`, `configs/`, `tests/{contract,integration,unit}/` | |
| 20 | - | - [ ] T003 [P] Configure Git repository with .gitignore for Go projects | |
| 21 | - | ||
| 22 | - | ## Phase 3.2: Dependency Installation | |
| 23 | - | ||
| 24 | - | - [ ] T004 [P] Install CLI dependencies: `go get github.com/spf13/cobra@latest github.com/spf13/viper@latest` | |
| 25 | - | - [ ] T005 [P] Install CGO-free database dependency: `go get github.com/ncruces/go-sqlite3@latest` | |
| 26 | - | - [ ] T006 [P] Install validation dependency: `go get github.com/go-playground/validator/v10@latest` | |
| 27 | - | - [ ] T007 [P] Install testing dependency: `go get github.com/stretchr/testify@latest` | |
| 28 | - | - [ ] T008 Install SQLC tool: `go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest` | |
| 29 | - | - [ ] T009 Install Wails v3-alpha tool: `go install github.com/wailsapp/wails/v3/cmd/wails@v3.0.0-alpha.28` | |
| 30 | - | ||
| 31 | - | ## Phase 3.3: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.4 | |
| 32 | - | ||
| 33 | - | **CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation** | |
| 34 | - | ||
| 35 | - | - [ ] T010 [P] Contract test for ModuleConfig validation in `tests/contract/test_module_config.go` | |
| 36 | - | - [ ] T011 [P] Contract test for CLI init command in `tests/contract/test_cli_init.go` | |
| 37 | - | - [ ] T012 [P] Contract test for dependency installation in `tests/contract/test_deps_install.go` | |
| 38 | - | - [ ] T013 [P] Integration test for full project initialization in `tests/integration/test_full_init.go` | |
| 39 | - | - [ ] T014 [P] Integration test for CGO-free database build in `tests/integration/test_cgo_free_build.go` | |
| 40 | - | - [ ] T015 [P] Integration test for Wails build (CGO required) in `tests/integration/test_wails_build.go` | |
| 41 | - | ||
| 42 | - | ## Phase 3.4: Core Implementation (ONLY after tests are failing) | |
| 43 | - | ||
| 44 | - | - [ ] T016 [P] ModuleConfig model in `internal/models/module.go` | |
| 45 | - | - [ ] T017 [P] ProjectStructure model in `internal/models/structure.go` | |
| 46 | - | - [ ] T018 [P] InstallationStatus model in `internal/models/status.go` | |
| 47 | - | - [ ] T019 CLI root command setup in `cmd/dumber/main.go` | |
| 48 | - | - [ ] T020 CLI init command implementation in `internal/cli/init.go` | |
| 49 | - | - [ ] T021 Dependency installer service in `internal/services/installer.go` | |
| 50 | - | - [ ] T022 Project structure creator in `internal/services/structure.go` | |
| 51 | - | - [ ] T023 Configuration file generator in `internal/services/config.go` | |
| 52 | - | ||
| 53 | - | ## Phase 3.5: Configuration Files | |
| 54 | - | ||
| 55 | - | - [ ] T024 [P] Generate SQLC configuration template in `configs/sqlc.yaml` | |
| 56 | - | - [ ] T025 [P] Generate Wails configuration template in `configs/wails.json` | |
| 57 | - | - [ ] T026 [P] Create initial database migration in `migrations/001_initial.sql` | |
| 58 | - | ||
| 59 | - | ## Phase 3.6: Verification and Integration | |
| 60 | - | ||
| 61 | - | - [ ] T027 Build verification with CGO_ENABLED=0 for core components | |
| 62 | - | - [ ] T028 Build verification with CGO_ENABLED=1 for Wails integration | |
| 63 | - | - [ ] T029 Dependency resolution verification with `go mod download` | |
| 64 | - | - [ ] T030 Tool availability verification: `sqlc version && wails version` | |
| 65 | - | ||
| 66 | - | ## Phase 3.7: Polish and Documentation | |
| 67 | - | ||
| 68 | - | - [ ] T031 [P] Unit tests for validation logic in `tests/unit/test_validation.go` | |
| 69 | - | - [ ] T032 [P] Unit tests for config generation in `tests/unit/test_config_gen.go` | |
| 70 | - | - [ ] T033 [P] Error handling and logging implementation | |
| 71 | - | - [ ] T034 Update quickstart.md with actual execution results | |
| 72 | - | - [ ] T035 Run full quickstart validation script | |
| 73 | - | ||
| 74 | - | ## Dependencies | |
| 75 | - | ||
| 76 | - | **Critical Path**: | |
| 77 | - | - Setup (T001-T003) before dependencies (T004-T009) | |
| 78 | - | - Dependencies before tests (T010-T015) | |
| 79 | - | - Tests (T010-T015) before implementation (T016-T023) | |
| 80 | - | - Core implementation before config files (T024-T026) | |
| 81 | - | - Everything before verification (T027-T030) | |
| 82 | - | ||
| 83 | - | **Specific Blockers**: | |
| 84 | - | - T001 blocks T004-T009 (need go.mod first) | |
| 85 | - | - T016-T018 block T021-T023 (need models for services) | |
| 86 | - | - T020 blocks T027-T030 (need CLI for verification) | |
| 87 | - | ||
| 88 | - | ## Parallel Execution Examples | |
| 89 | - | ||
| 90 | - | ### Install Dependencies Concurrently | |
| 91 | - | ```bash | |
| 92 | - | # Launch T004-T007 together (different packages): | |
| 93 | - | Task: "Install CLI dependencies: go get github.com/spf13/cobra@latest github.com/spf13/viper@latest" | |
| 94 | - | Task: "Install CGO-free database dependency: go get github.com/ncruces/go-sqlite3@latest" | |
| 95 | - | Task: "Install validation dependency: go get github.com/go-playground/validator/v10@latest" | |
| 96 | - | Task: "Install testing dependency: go get github.com/stretchr/testify@latest" | |
| 97 | - | ``` | |
| 98 | - | ||
| 99 | - | ### Write Tests Concurrently | |
| 100 | - | ```bash | |
| 101 | - | # Launch T010-T015 together (different test files): | |
| 102 | - | Task: "Contract test for ModuleConfig validation in tests/contract/test_module_config.go" | |
| 103 | - | Task: "Contract test for CLI init command in tests/contract/test_cli_init.go" | |
| 104 | - | Task: "Contract test for dependency installation in tests/contract/test_deps_install.go" | |
| 105 | - | Task: "Integration test for full project initialization in tests/integration/test_full_init.go" | |
| 106 | - | Task: "Integration test for CGO-free database build in tests/integration/test_cgo_free_build.go" | |
| 107 | - | Task: "Integration test for Wails build (CGO required) in tests/integration/test_wails_build.go" | |
| 108 | - | ``` | |
| 109 | - | ||
| 110 | - | ### Create Models Concurrently | |
| 111 | - | ```bash | |
| 112 | - | # Launch T016-T018 together (different model files): | |
| 113 | - | Task: "ModuleConfig model in internal/models/module.go" | |
| 114 | - | Task: "ProjectStructure model in internal/models/structure.go" | |
| 115 | - | Task: "InstallationStatus model in internal/models/status.go" | |
| 116 | - | ``` | |
| 117 | - | ||
| 118 | - | ## CGO Optimization Strategy | |
| 119 | - | ||
| 120 | - | **CGO-Free Development** (T004-T007, T010-T014, T016-T023): | |
| 121 | - | - Most tasks can run with `CGO_ENABLED=0` | |
| 122 | - | - Database layer uses ncruces/go-sqlite3 (CGO-free) | |
| 123 | - | - CLI and parser components don't need CGO | |
| 124 | - | - Faster development cycle for majority of work | |
| 125 | - | ||
| 126 | - | **CGO Required** (T009, T015, T028): | |
| 127 | - | - Only Wails installation and integration requires `CGO_ENABLED=1` | |
| 128 | - | - WebKit2GTK bindings need CGO for native rendering | |
| 129 | - | - Clear separation allows independent development | |
| 130 | - | ||
| 131 | - | ## Notes | |
| 132 | - | ||
| 133 | - | - [P] tasks = different files, no dependencies | |
| 134 | - | - Verify tests fail before implementing (TDD enforcement) | |
| 135 | - | - Use `go get @latest` for all dependencies per user requirements | |
| 136 | - | - Commit after each task completion | |
| 137 | - | - CGO-free SQLite driver (ncruces) allows faster development cycle | |
| 138 | - | - Only Wails final integration requires CGO | |
| 139 | - | ||
| 140 | - | ## Task Generation Rules Applied | |
| 141 | - | ||
| 142 | - | 1. **From Contracts**: | |
| 143 | - | - cli-commands.md → T011, T020 (CLI init command) | |
| 144 | - | - go-module.yaml → T010, T012 (module and dependency contracts) | |
| 145 | - | ||
| 146 | - | 2. **From Data Model**: | |
| 147 | - | - ModuleConfig → T016 (model creation) | |
| 148 | - | - ProjectStructure → T017 (model creation) | |
| 149 | - | - InstallationStatus → T018 (model creation) | |
| 150 | - | ||
| 151 | - | 3. **From Research Decisions**: | |
| 152 | - | - CGO-free SQLite → T005, T014 (specific driver selection) | |
| 153 | - | - Wails v3-alpha → T009, T015 (version-specific installation) | |
| 154 | - | ||
| 155 | - | 4. **From Quickstart Scenarios**: | |
| 156 | - | - Full initialization → T013 (integration test) | |
| 157 | - | - Build verification → T027, T028 (CGO separation tests) | |
| 158 | - | - Tool availability → T030 (verification scenario) | |
| 159 | - | ||
| 160 | - | ## Validation Checklist | |
| 161 | - | ||
| 162 | - | - [x] All contracts have corresponding tests (T010-T012) | |
| 163 | - | - [x] All entities have model tasks (T016-T018) | |
| 164 | - | - [x] All tests come before implementation (T010-T015 before T016-T023) | |
| 165 | - | - [x] Parallel tasks truly independent ([P] tasks use different files) | |
| 166 | - | - [x] Each task specifies exact file path | |
| 167 | - | - [x] No task modifies same file as another [P] task | |
| 168 | - | - [x] TDD principles enforced (tests must fail before implementation) | |
| 169 | - | - [x] CGO optimization strategy clearly defined | |
| 170 | - | - [x] Dependencies properly ordered and documented⏎̸ | |
D specs/002-browser-controls-ui/contracts/browser-controls-api.yaml +0 -258
| @@ -1,258 +0,0 @@ | |||
| 1 | - | openapi: 3.0.3 | |
| 2 | - | info: | |
| 3 | - | title: Browser Controls API | |
| 4 | - | description: Wails backend API for browser keyboard and mouse controls | |
| 5 | - | version: 0.1.0 | |
| 6 | - | ||
| 7 | - | paths: | |
| 8 | - | /zoom/in: | |
| 9 | - | post: | |
| 10 | - | summary: Zoom in to next higher level | |
| 11 | - | description: Increases zoom level to next Firefox standard zoom level (FR-001) | |
| 12 | - | requestBody: | |
| 13 | - | required: true | |
| 14 | - | content: | |
| 15 | - | application/json: | |
| 16 | - | schema: | |
| 17 | - | type: object | |
| 18 | - | properties: | |
| 19 | - | domain: | |
| 20 | - | type: string | |
| 21 | - | description: Current website domain for persistence | |
| 22 | - | example: "github.com" | |
| 23 | - | required: | |
| 24 | - | - domain | |
| 25 | - | responses: | |
| 26 | - | '200': | |
| 27 | - | description: Zoom level successfully increased | |
| 28 | - | content: | |
| 29 | - | application/json: | |
| 30 | - | schema: | |
| 31 | - | $ref: '#/components/schemas/ZoomResponse' | |
| 32 | - | '400': | |
| 33 | - | description: Invalid domain or already at maximum zoom | |
| 34 | - | content: | |
| 35 | - | application/json: | |
| 36 | - | schema: | |
| 37 | - | $ref: '#/components/schemas/ErrorResponse' | |
| 38 | - | ||
| 39 | - | /zoom/out: | |
| 40 | - | post: | |
| 41 | - | summary: Zoom out to next lower level | |
| 42 | - | description: Decreases zoom level to next Firefox standard zoom level (FR-002) | |
| 43 | - | requestBody: | |
| 44 | - | required: true | |
| 45 | - | content: | |
| 46 | - | application/json: | |
| 47 | - | schema: | |
| 48 | - | type: object | |
| 49 | - | properties: | |
| 50 | - | domain: | |
| 51 | - | type: string | |
| 52 | - | description: Current website domain for persistence | |
| 53 | - | example: "stackoverflow.com" | |
| 54 | - | required: | |
| 55 | - | - domain | |
| 56 | - | responses: | |
| 57 | - | '200': | |
| 58 | - | description: Zoom level successfully decreased | |
| 59 | - | content: | |
| 60 | - | application/json: | |
| 61 | - | schema: | |
| 62 | - | $ref: '#/components/schemas/ZoomResponse' | |
| 63 | - | '400': | |
| 64 | - | description: Invalid domain or already at minimum zoom | |
| 65 | - | content: | |
| 66 | - | application/json: | |
| 67 | - | schema: | |
| 68 | - | $ref: '#/components/schemas/ErrorResponse' | |
| 69 | - | ||
| 70 | - | /navigation/back: | |
| 71 | - | post: | |
| 72 | - | summary: Navigate to previous page in history | |
| 73 | - | description: Navigates to previous page if history exists (FR-003, FR-010) | |
| 74 | - | responses: | |
| 75 | - | '200': | |
| 76 | - | description: Successfully navigated back | |
| 77 | - | content: | |
| 78 | - | application/json: | |
| 79 | - | schema: | |
| 80 | - | $ref: '#/components/schemas/NavigationResponse' | |
| 81 | - | '204': | |
| 82 | - | description: No history available, no action taken | |
| 83 | - | '500': | |
| 84 | - | description: Navigation error | |
| 85 | - | content: | |
| 86 | - | application/json: | |
| 87 | - | schema: | |
| 88 | - | $ref: '#/components/schemas/ErrorResponse' | |
| 89 | - | ||
| 90 | - | /navigation/forward: | |
| 91 | - | post: | |
| 92 | - | summary: Navigate to next page in history | |
| 93 | - | description: Navigates to next page if forward history exists (FR-004, FR-010) | |
| 94 | - | responses: | |
| 95 | - | '200': | |
| 96 | - | description: Successfully navigated forward | |
| 97 | - | content: | |
| 98 | - | application/json: | |
| 99 | - | schema: | |
| 100 | - | $ref: '#/components/schemas/NavigationResponse' | |
| 101 | - | '204': | |
| 102 | - | description: No forward history available, no action taken | |
| 103 | - | '500': | |
| 104 | - | description: Navigation error | |
| 105 | - | content: | |
| 106 | - | application/json: | |
| 107 | - | schema: | |
| 108 | - | $ref: '#/components/schemas/ErrorResponse' | |
| 109 | - | ||
| 110 | - | /clipboard/copy-url: | |
| 111 | - | post: | |
| 112 | - | summary: Copy current URL to system clipboard | |
| 113 | - | description: Copies current page URL using wlcopy/xclip/xsel fallback (FR-005, FR-006, FR-011) | |
| 114 | - | requestBody: | |
| 115 | - | required: true | |
| 116 | - | content: | |
| 117 | - | application/json: | |
| 118 | - | schema: | |
| 119 | - | type: object | |
| 120 | - | properties: | |
| 121 | - | url: | |
| 122 | - | type: string | |
| 123 | - | format: uri | |
| 124 | - | description: Current page URL to copy | |
| 125 | - | example: "https://github.com/bnema/dumber" | |
| 126 | - | required: | |
| 127 | - | - url | |
| 128 | - | responses: | |
| 129 | - | '200': | |
| 130 | - | description: URL successfully copied to clipboard | |
| 131 | - | content: | |
| 132 | - | application/json: | |
| 133 | - | schema: | |
| 134 | - | type: object | |
| 135 | - | properties: | |
| 136 | - | success: | |
| 137 | - | type: boolean | |
| 138 | - | example: true | |
| 139 | - | tool_used: | |
| 140 | - | type: string | |
| 141 | - | enum: ["wlcopy", "xclip", "xsel"] | |
| 142 | - | example: "wlcopy" | |
| 143 | - | message: | |
| 144 | - | type: string | |
| 145 | - | example: "URL copied to clipboard using wlcopy" | |
| 146 | - | '500': | |
| 147 | - | description: All clipboard tools failed | |
| 148 | - | content: | |
| 149 | - | application/json: | |
| 150 | - | schema: | |
| 151 | - | $ref: '#/components/schemas/ErrorResponse' | |
| 152 | - | ||
| 153 | - | /zoom/get-level: | |
| 154 | - | get: | |
| 155 | - | summary: Get current zoom level for domain | |
| 156 | - | description: Retrieves persisted zoom level for specific domain (FR-009) | |
| 157 | - | parameters: | |
| 158 | - | - name: domain | |
| 159 | - | in: query | |
| 160 | - | required: true | |
| 161 | - | schema: | |
| 162 | - | type: string | |
| 163 | - | description: Website domain to query | |
| 164 | - | example: "reddit.com" | |
| 165 | - | responses: | |
| 166 | - | '200': | |
| 167 | - | description: Zoom level retrieved | |
| 168 | - | content: | |
| 169 | - | application/json: | |
| 170 | - | schema: | |
| 171 | - | $ref: '#/components/schemas/ZoomResponse' | |
| 172 | - | '404': | |
| 173 | - | description: No zoom level stored for domain (defaults to 100%) | |
| 174 | - | content: | |
| 175 | - | application/json: | |
| 176 | - | schema: | |
| 177 | - | $ref: '#/components/schemas/ZoomResponse' | |
| 178 | - | ||
| 179 | - | components: | |
| 180 | - | schemas: | |
| 181 | - | ZoomResponse: | |
| 182 | - | type: object | |
| 183 | - | properties: | |
| 184 | - | zoom_factor: | |
| 185 | - | type: number | |
| 186 | - | format: float | |
| 187 | - | description: Current zoom level as decimal (1.0 = 100%) | |
| 188 | - | minimum: 0.3 | |
| 189 | - | maximum: 5.0 | |
| 190 | - | example: 1.2 | |
| 191 | - | zoom_percentage: | |
| 192 | - | type: integer | |
| 193 | - | description: Zoom level as percentage for UI display | |
| 194 | - | minimum: 30 | |
| 195 | - | maximum: 500 | |
| 196 | - | example: 120 | |
| 197 | - | is_firefox_level: | |
| 198 | - | type: boolean | |
| 199 | - | description: Whether zoom level matches Firefox standard levels | |
| 200 | - | example: true | |
| 201 | - | domain: | |
| 202 | - | type: string | |
| 203 | - | description: Domain this zoom level applies to | |
| 204 | - | example: "github.com" | |
| 205 | - | ||
| 206 | - | NavigationResponse: | |
| 207 | - | type: object | |
| 208 | - | properties: | |
| 209 | - | url: | |
| 210 | - | type: string | |
| 211 | - | format: uri | |
| 212 | - | description: Target URL to navigate to | |
| 213 | - | example: "https://previous-page.com" | |
| 214 | - | title: | |
| 215 | - | type: string | |
| 216 | - | description: Page title if available | |
| 217 | - | example: "Previous Page Title" | |
| 218 | - | history_index: | |
| 219 | - | type: integer | |
| 220 | - | description: New position in history after navigation | |
| 221 | - | example: 2 | |
| 222 | - | can_go_back: | |
| 223 | - | type: boolean | |
| 224 | - | description: Whether back navigation is still available | |
| 225 | - | example: true | |
| 226 | - | can_go_forward: | |
| 227 | - | type: boolean | |
| 228 | - | description: Whether forward navigation is available | |
| 229 | - | example: false | |
| 230 | - | ||
| 231 | - | ErrorResponse: | |
| 232 | - | type: object | |
| 233 | - | properties: | |
| 234 | - | error: | |
| 235 | - | type: string | |
| 236 | - | description: Human-readable error message | |
| 237 | - | example: "Already at maximum zoom level" | |
| 238 | - | error_code: | |
| 239 | - | type: string | |
| 240 | - | description: Machine-readable error identifier | |
| 241 | - | example: "MAX_ZOOM_REACHED" | |
| 242 | - | timestamp: | |
| 243 | - | type: string | |
| 244 | - | format: date-time | |
| 245 | - | description: Error occurrence timestamp | |
| 246 | - | example: "2025-09-09T10:30:00Z" | |
| 247 | - | ||
| 248 | - | # Wails Service Methods (Go Implementation) | |
| 249 | - | # These correspond to the HTTP API but are called directly via Wails context: | |
| 250 | - | # | |
| 251 | - | # type BrowserControlService struct{} | |
| 252 | - | # | |
| 253 | - | # func (s *BrowserControlService) ZoomIn(ctx context.Context, domain string) (*ZoomResponse, error) | |
| 254 | - | # func (s *BrowserControlService) ZoomOut(ctx context.Context, domain string) (*ZoomResponse, error) | |
| 255 | - | # func (s *BrowserControlService) NavigateBack(ctx context.Context) (*NavigationResponse, error) | |
| 256 | - | # func (s *BrowserControlService) NavigateForward(ctx context.Context) (*NavigationResponse, error) | |
| 257 | - | # func (s *BrowserControlService) CopyCurrentURL(ctx context.Context, url string) (*ClipboardResponse, error) | |
| 258 | - | # func (s *BrowserControlService) GetZoomLevel(ctx context.Context, domain string) (*ZoomResponse, error)⏎̸ | |
D specs/002-browser-controls-ui/data-model.md +0 -165
| @@ -1,165 +0,0 @@ | |||
| 1 | - | # Data Model: Browser Controls UI | |
| 2 | - | ||
| 3 | - | ## Entities | |
| 4 | - | ||
| 5 | - | ### 1. ZoomLevel | |
| 6 | - | Represents domain-specific zoom preferences for persistent user experience. | |
| 7 | - | ||
| 8 | - | **Fields**: | |
| 9 | - | - `Domain` (string, primary key): Website domain (e.g., "github.com", "stackoverflow.com") | |
| 10 | - | - `ZoomFactor` (float64): Zoom multiplier (0.3 to 5.0 range, default 1.0) | |
| 11 | - | - `UpdatedAt` (time.Time): Timestamp of last zoom level change | |
| 12 | - | ||
| 13 | - | **Validation Rules**: | |
| 14 | - | - Domain must be valid hostname format | |
| 15 | - | - ZoomFactor must be within Firefox range: 0.30 ≤ zoom ≤ 5.00 | |
| 16 | - | - ZoomFactor must match standard Firefox zoom levels (30%, 50%, 67%, 80%, 90%, 100%, 110%, 120%, 133%, 150%, 170%, 200%, 240%, 300%, 400%, 500%) | |
| 17 | - | - UpdatedAt automatically set on creation/update | |
| 18 | - | ||
| 19 | - | **Relationships**: | |
| 20 | - | - One-to-one with website domains | |
| 21 | - | - No foreign key relationships (standalone entity) | |
| 22 | - | ||
| 23 | - | ### 2. BrowserState (Extended) | |
| 24 | - | Existing entity extended with zoom and navigation state management. | |
| 25 | - | ||
| 26 | - | **New Fields**: | |
| 27 | - | - `CurrentZoomLevel` (float64): Active zoom level for current page | |
| 28 | - | - `NavigationHistory` ([]HistoryEntry): Back/forward navigation stack | |
| 29 | - | - `HistoryIndex` (int): Current position in navigation history | |
| 30 | - | ||
| 31 | - | **State Transitions**: | |
| 32 | - | - Zoom In: CurrentZoomLevel → Next higher Firefox zoom level | |
| 33 | - | - Zoom Out: CurrentZoomLevel → Next lower Firefox zoom level | |
| 34 | - | - Navigate Back: HistoryIndex decrements (if > 0) | |
| 35 | - | - Navigate Forward: HistoryIndex increments (if < len(NavigationHistory)-1) | |
| 36 | - | - URL Change: Update CurrentZoomLevel from ZoomLevel persistence | |
| 37 | - | ||
| 38 | - | **Validation Rules**: | |
| 39 | - | - CurrentZoomLevel follows same rules as ZoomLevel.ZoomFactor | |
| 40 | - | - HistoryIndex must be valid array index (0 ≤ index < len(NavigationHistory)) | |
| 41 | - | - NavigationHistory maintained as bounded array (configurable max size) | |
| 42 | - | ||
| 43 | - | ### 3. KeyboardEvent (Transient) | |
| 44 | - | Represents keyboard input events for processing. | |
| 45 | - | ||
| 46 | - | **Fields**: | |
| 47 | - | - `Key` (string): Key identifier ("=", "-", "c") | |
| 48 | - | - `Modifiers` ([]string): Active modifier keys (["ctrl"], ["ctrl", "shift"]) | |
| 49 | - | - `Timestamp` (time.Time): Event occurrence time | |
| 50 | - | ||
| 51 | - | **Validation Rules**: | |
| 52 | - | - Key must be non-empty string | |
| 53 | - | - Modifiers must be valid modifier keys ("ctrl", "shift", "alt", "meta") | |
| 54 | - | - Timestamp must be recent (within reasonable event processing window) | |
| 55 | - | ||
| 56 | - | **State Transitions**: | |
| 57 | - | - Ctrl+Plus → ZoomIn action | |
| 58 | - | - Ctrl+Minus → ZoomOut action | |
| 59 | - | - Ctrl+Shift+C → CopyURL action | |
| 60 | - | ||
| 61 | - | ### 4. MouseEvent (Transient) | |
| 62 | - | Represents mouse button events for navigation. | |
| 63 | - | ||
| 64 | - | **Fields**: | |
| 65 | - | - `Button` (int): Mouse button identifier (3=back, 4=forward) | |
| 66 | - | - `EventType` (string): Event type ("mousedown", "mouseup") | |
| 67 | - | - `Timestamp` (time.Time): Event occurrence time | |
| 68 | - | ||
| 69 | - | **Validation Rules**: | |
| 70 | - | - Button must be 3 (back) or 4 (forward) | |
| 71 | - | - EventType must be valid mouse event type | |
| 72 | - | - Only "mousedown" events trigger navigation actions | |
| 73 | - | ||
| 74 | - | **State Transitions**: | |
| 75 | - | - Button 3 mousedown → NavigateBack action | |
| 76 | - | - Button 4 mousedown → NavigateForward action | |
| 77 | - | ||
| 78 | - | ## Database Schema Changes | |
| 79 | - | ||
| 80 | - | ### New Table: zoom_levels | |
| 81 | - | ```sql | |
| 82 | - | CREATE TABLE zoom_levels ( | |
| 83 | - | domain TEXT PRIMARY KEY, | |
| 84 | - | zoom_factor REAL NOT NULL DEFAULT 1.0 CHECK(zoom_factor >= 0.3 AND zoom_factor <= 5.0), | |
| 85 | - | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| 86 | - | ); | |
| 87 | - | ||
| 88 | - | CREATE INDEX idx_zoom_levels_updated_at ON zoom_levels(updated_at); | |
| 89 | - | ``` | |
| 90 | - | ||
| 91 | - | ### SQLC Queries | |
| 92 | - | ```sql | |
| 93 | - | -- name: GetZoomLevel :one | |
| 94 | - | SELECT zoom_factor FROM zoom_levels WHERE domain = ?; | |
| 95 | - | ||
| 96 | - | -- name: SetZoomLevel :exec | |
| 97 | - | INSERT OR REPLACE INTO zoom_levels (domain, zoom_factor, updated_at) | |
| 98 | - | VALUES (?, ?, CURRENT_TIMESTAMP); | |
| 99 | - | ||
| 100 | - | -- name: CleanupOldZoomLevels :exec | |
| 101 | - | DELETE FROM zoom_levels WHERE updated_at < date('now', '-30 days'); | |
| 102 | - | ``` | |
| 103 | - | ||
| 104 | - | ## Data Flow | |
| 105 | - | ||
| 106 | - | ### Zoom Operations | |
| 107 | - | 1. User triggers zoom event → JavaScript captures keyboard event | |
| 108 | - | 2. Frontend calls backend `ZoomIn()` or `ZoomOut()` method | |
| 109 | - | 3. Backend calculates next valid Firefox zoom level | |
| 110 | - | 4. Backend updates BrowserState.CurrentZoomLevel | |
| 111 | - | 5. Backend persists to database via `SetZoomLevel` | |
| 112 | - | 6. Frontend applies CSS zoom styling | |
| 113 | - | 7. Optional: Visual feedback notification | |
| 114 | - | ||
| 115 | - | ### Navigation Operations | |
| 116 | - | 1. User triggers mouse back/forward → JavaScript captures mouse event | |
| 117 | - | 2. Frontend calls backend `NavigateBack()` or `NavigateForward()` method | |
| 118 | - | 3. Backend validates navigation history bounds | |
| 119 | - | 4. Backend updates BrowserState.HistoryIndex | |
| 120 | - | 5. Backend returns target URL from history | |
| 121 | - | 6. Frontend navigates WebView to target URL | |
| 122 | - | ||
| 123 | - | ### URL Copy Operation | |
| 124 | - | 1. User triggers Ctrl+Shift+C → JavaScript captures keyboard event | |
| 125 | - | 2. Frontend calls backend `CopyCurrentURL()` method | |
| 126 | - | 3. Backend retrieves current URL from BrowserState | |
| 127 | - | 4. Backend executes clipboard tool chain (wlcopy → xclip → xsel) | |
| 128 | - | 5. Backend returns success/failure status | |
| 129 | - | 6. Optional: Visual feedback notification | |
| 130 | - | ||
| 131 | - | ## Validation Strategy | |
| 132 | - | ||
| 133 | - | ### Input Validation | |
| 134 | - | - All user inputs validated at service layer entry points | |
| 135 | - | - Zoom levels constrained to Firefox standard values | |
| 136 | - | - Navigation bounds checking prevents array index errors | |
| 137 | - | - URL validation for copy operations | |
| 138 | - | ||
| 139 | - | ### Data Integrity | |
| 140 | - | - SQLite constraints enforce zoom level ranges | |
| 141 | - | - Database transactions for atomic state updates | |
| 142 | - | - Error handling for clipboard tool failures | |
| 143 | - | - Graceful degradation when tools unavailable | |
| 144 | - | ||
| 145 | - | ### Performance Considerations | |
| 146 | - | - Zoom level persistence debounced to prevent excessive DB writes | |
| 147 | - | - Navigation history bounded to prevent memory growth | |
| 148 | - | - Database cleanup for old zoom preferences | |
| 149 | - | - Prepared statements for repeated queries | |
| 150 | - | ||
| 151 | - | ## Error Handling | |
| 152 | - | ||
| 153 | - | ### Domain Errors | |
| 154 | - | - Invalid zoom level → clamp to nearest valid value | |
| 155 | - | - Empty navigation history → silent no-op | |
| 156 | - | - Invalid clipboard tool → try next in fallback chain | |
| 157 | - | - Malformed URL → log error, return failure status | |
| 158 | - | ||
| 159 | - | ### System Errors | |
| 160 | - | - Database unavailable → continue with in-memory state only | |
| 161 | - | - Clipboard tools unavailable → user notification, graceful degradation | |
| 162 | - | - WebView navigation failure → restore previous state | |
| 163 | - | - Event processing errors → log and continue | |
| 164 | - | ||
| 165 | - | All data models maintain constitutional principles of simplicity and performance while providing robust user experience for browser control operations.⏎̸ | |
D specs/002-browser-controls-ui/plan.md +0 -237
| @@ -1,237 +0,0 @@ | |||
| 1 | - | # Implementation Plan: Browser Controls UI | |
| 2 | - | ||
| 3 | - | **Branch**: `002-browser-controls-ui` | **Date**: 2025-09-09 | **Spec**: [spec.md](./spec.md) | |
| 4 | - | **Input**: Feature specification from `/home/brice/dev/projects/dumb-browser/specs/002-browser-controls-ui/spec.md` | |
| 5 | - | ||
| 6 | - | ## Execution Flow (/plan command scope) | |
| 7 | - | ``` | |
| 8 | - | 1. Load feature spec from Input path | |
| 9 | - | → If not found: ERROR "No feature spec at {path}" | |
| 10 | - | 2. Fill Technical Context (scan for NEEDS CLARIFICATION) | |
| 11 | - | → Detect Project Type from context (web=frontend+backend, mobile=app+api) | |
| 12 | - | → Set Structure Decision based on project type | |
| 13 | - | 3. Evaluate Constitution Check section below | |
| 14 | - | → If violations exist: Document in Complexity Tracking | |
| 15 | - | → If no justification possible: ERROR "Simplify approach first" | |
| 16 | - | → Update Progress Tracking: Initial Constitution Check | |
| 17 | - | 4. Execute Phase 0 → research.md | |
| 18 | - | → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns" | |
| 19 | - | 5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI). | |
| 20 | - | 6. Re-evaluate Constitution Check section | |
| 21 | - | → If new violations: Refactor design, return to Phase 1 | |
| 22 | - | → Update Progress Tracking: Post-Design Constitution Check | |
| 23 | - | 7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) | |
| 24 | - | 8. STOP - Ready for /tasks command | |
| 25 | - | ``` | |
| 26 | - | ||
| 27 | - | **IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands: | |
| 28 | - | - Phase 2: /tasks command creates tasks.md | |
| 29 | - | - Phase 3-4: Implementation execution (manual or via tools) | |
| 30 | - | ||
| 31 | - | ## Summary | |
| 32 | - | Implement keyboard and mouse navigation controls for the Wails-based browser: zoom in/out with Ctrl+/-, back/forward navigation with mouse buttons, URL copying with Ctrl+Shift+C, and dynamic window title updates. This feature enhances user experience with standard browser controls while maintaining the application's speed-first principle and single-binary architecture. | |
| 33 | - | ||
| 34 | - | ## Technical Context | |
| 35 | - | **Language/Version**: Go 1.25.1 | |
| 36 | - | **Primary Dependencies**: Wails v3-alpha.28 (WebView), Cobra (CLI), Viper (config), SQLite3 | |
| 37 | - | **Storage**: SQLite3 database for history/zoom persistence | |
| 38 | - | **Testing**: Go standard testing, manual verification with keyboard/mouse controls | |
| 39 | - | **Target Platform**: Linux desktop (Wayland native, tiling WM compatible) | |
| 40 | - | **Project Type**: single (desktop application with embedded frontend) | |
| 41 | - | **Performance Goals**: <500ms startup, <100MB baseline memory, <50ms history search | |
| 42 | - | **Constraints**: Single binary, no external runtime deps, WebKit2GTK system integration | |
| 43 | - | **Scale/Scope**: Single user desktop app, ~12 functional requirements, 5 new keyboard/mouse controls | |
| 44 | - | ||
| 45 | - | ## Constitution Check | |
| 46 | - | *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | |
| 47 | - | ||
| 48 | - | **Simplicity**: | |
| 49 | - | - Projects: 1 (single desktop app with embedded frontend) ✓ | |
| 50 | - | - Using framework directly? Yes (direct Wails v3 integration, no wrappers) ✓ | |
| 51 | - | - Single data model? Yes (existing browser state, minimal zoom state addition) ✓ | |
| 52 | - | - Avoiding patterns? Yes (direct service calls, no unnecessary abstractions) ✓ | |
| 53 | - | ||
| 54 | - | **Architecture**: | |
| 55 | - | - EVERY feature as library? Yes (keyboard/mouse controls as separate service methods) ✓ | |
| 56 | - | - Libraries listed: BrowserService (navigation/zoom), ConfigService (persistence) | |
| 57 | - | - CLI per library: Existing CLI structure maintained, no new commands needed ✓ | |
| 58 | - | - Library docs: N/A (internal desktop app, not library distribution) | |
| 59 | - | ||
| 60 | - | **Testing (NON-NEGOTIABLE)**: | |
| 61 | - | - RED-GREEN-Refactor cycle enforced? Yes (will create failing tests first) ✓ | |
| 62 | - | - Git commits show tests before implementation? Yes (test commits before feature commits) ✓ | |
| 63 | - | - Order: Contract→Integration→E2E→Unit strictly followed? Yes ✓ | |
| 64 | - | - Real dependencies used? Yes (real SQLite, real Wails WebView) ✓ | |
| 65 | - | - Integration tests for: Keyboard event handling, zoom persistence, clipboard integration ✓ | |
| 66 | - | - FORBIDDEN: Implementation before test, skipping RED phase ✓ | |
| 67 | - | ||
| 68 | - | **Observability**: | |
| 69 | - | - Structured logging included? Yes (existing slog usage maintained) ✓ | |
| 70 | - | - Frontend logs → backend? Yes (Wails provides unified logging) ✓ | |
| 71 | - | - Error context sufficient? Yes (proper Go error handling) ✓ | |
| 72 | - | ||
| 73 | - | **Versioning**: | |
| 74 | - | - Version number assigned? Using existing versioning (0.1.0 → 0.1.1) ✓ | |
| 75 | - | - BUILD increments on every change? Yes (patch version bump) ✓ | |
| 76 | - | - Breaking changes handled? None expected (additive feature only) ✓ | |
| 77 | - | ||
| 78 | - | ## Project Structure | |
| 79 | - | ||
| 80 | - | ### Documentation (this feature) | |
| 81 | - | ``` | |
| 82 | - | specs/[###-feature]/ | |
| 83 | - | ├── plan.md # This file (/plan command output) | |
| 84 | - | ├── research.md # Phase 0 output (/plan command) | |
| 85 | - | ├── data-model.md # Phase 1 output (/plan command) | |
| 86 | - | ├── quickstart.md # Phase 1 output (/plan command) | |
| 87 | - | ├── contracts/ # Phase 1 output (/plan command) | |
| 88 | - | └── tasks.md # Phase 2 output (/tasks command - NOT created by /plan) | |
| 89 | - | ``` | |
| 90 | - | ||
| 91 | - | ### Source Code (repository root) | |
| 92 | - | ``` | |
| 93 | - | # Option 1: Single project (DEFAULT) | |
| 94 | - | src/ | |
| 95 | - | ├── models/ | |
| 96 | - | ├── services/ | |
| 97 | - | ├── cli/ | |
| 98 | - | └── lib/ | |
| 99 | - | ||
| 100 | - | tests/ | |
| 101 | - | ├── contract/ | |
| 102 | - | ├── integration/ | |
| 103 | - | └── unit/ | |
| 104 | - | ||
| 105 | - | # Option 2: Web application (when "frontend" + "backend" detected) | |
| 106 | - | backend/ | |
| 107 | - | ├── src/ | |
| 108 | - | │ ├── models/ | |
| 109 | - | │ ├── services/ | |
| 110 | - | │ └── api/ | |
| 111 | - | └── tests/ | |
| 112 | - | ||
| 113 | - | frontend/ | |
| 114 | - | ├── src/ | |
| 115 | - | │ ├── components/ | |
| 116 | - | │ ├── pages/ | |
| 117 | - | │ └── services/ | |
| 118 | - | └── tests/ | |
| 119 | - | ||
| 120 | - | # Option 3: Mobile + API (when "iOS/Android" detected) | |
| 121 | - | api/ | |
| 122 | - | └── [same as backend above] | |
| 123 | - | ||
| 124 | - | ios/ or android/ | |
| 125 | - | └── [platform-specific structure] | |
| 126 | - | ``` | |
| 127 | - | ||
| 128 | - | **Structure Decision**: Option 1 (Single project) - Desktop application with embedded frontend, existing structure maintained | |
| 129 | - | ||
| 130 | - | ## Phase 0: Outline & Research | |
| 131 | - | 1. **Extract unknowns from Technical Context** above: | |
| 132 | - | - For each NEEDS CLARIFICATION → research task | |
| 133 | - | - For each dependency → best practices task | |
| 134 | - | - For each integration → patterns task | |
| 135 | - | ||
| 136 | - | 2. **Generate and dispatch research agents**: | |
| 137 | - | ``` | |
| 138 | - | For each unknown in Technical Context: | |
| 139 | - | Task: "Research {unknown} for {feature context}" | |
| 140 | - | For each technology choice: | |
| 141 | - | Task: "Find best practices for {tech} in {domain}" | |
| 142 | - | ``` | |
| 143 | - | ||
| 144 | - | 3. **Consolidate findings** in `research.md` using format: | |
| 145 | - | - Decision: [what was chosen] | |
| 146 | - | - Rationale: [why chosen] | |
| 147 | - | - Alternatives considered: [what else evaluated] | |
| 148 | - | ||
| 149 | - | **Output**: research.md with all NEEDS CLARIFICATION resolved | |
| 150 | - | ||
| 151 | - | ## Phase 1: Design & Contracts | |
| 152 | - | *Prerequisites: research.md complete* | |
| 153 | - | ||
| 154 | - | 1. **Extract entities from feature spec** → `data-model.md`: | |
| 155 | - | - Entity name, fields, relationships | |
| 156 | - | - Validation rules from requirements | |
| 157 | - | - State transitions if applicable | |
| 158 | - | ||
| 159 | - | 2. **Generate API contracts** from functional requirements: | |
| 160 | - | - For each user action → endpoint | |
| 161 | - | - Use standard REST/GraphQL patterns | |
| 162 | - | - Output OpenAPI/GraphQL schema to `/contracts/` | |
| 163 | - | ||
| 164 | - | 3. **Generate contract tests** from contracts: | |
| 165 | - | - One test file per endpoint | |
| 166 | - | - Assert request/response schemas | |
| 167 | - | - Tests must fail (no implementation yet) | |
| 168 | - | ||
| 169 | - | 4. **Extract test scenarios** from user stories: | |
| 170 | - | - Each story → integration test scenario | |
| 171 | - | - Quickstart test = story validation steps | |
| 172 | - | ||
| 173 | - | 5. **Update agent file incrementally** (O(1) operation): | |
| 174 | - | - Run `/scripts/update-agent-context.sh [claude|gemini|copilot]` for your AI assistant | |
| 175 | - | - If exists: Add only NEW tech from current plan | |
| 176 | - | - Preserve manual additions between markers | |
| 177 | - | - Update recent changes (keep last 3) | |
| 178 | - | - Keep under 150 lines for token efficiency | |
| 179 | - | - Output to repository root | |
| 180 | - | ||
| 181 | - | **Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file | |
| 182 | - | ||
| 183 | - | ## Phase 2: Task Planning Approach | |
| 184 | - | *This section describes what the /tasks command will do - DO NOT execute during /plan* | |
| 185 | - | ||
| 186 | - | **Task Generation Strategy**: | |
| 187 | - | - Load `/templates/tasks-template.md` as base | |
| 188 | - | - Generate tasks from Phase 1 design docs (contracts, data model, quickstart) | |
| 189 | - | - Each contract → contract test task [P] | |
| 190 | - | - Each entity → model creation task [P] | |
| 191 | - | - Each user story → integration test task | |
| 192 | - | - Implementation tasks to make tests pass | |
| 193 | - | ||
| 194 | - | **Ordering Strategy**: | |
| 195 | - | - TDD order: Tests before implementation | |
| 196 | - | - Dependency order: Models before services before UI | |
| 197 | - | - Mark [P] for parallel execution (independent files) | |
| 198 | - | ||
| 199 | - | **Estimated Output**: 25-30 numbered, ordered tasks in tasks.md | |
| 200 | - | ||
| 201 | - | **IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan | |
| 202 | - | ||
| 203 | - | ## Phase 3+: Future Implementation | |
| 204 | - | *These phases are beyond the scope of the /plan command* | |
| 205 | - | ||
| 206 | - | **Phase 3**: Task execution (/tasks command creates tasks.md) | |
| 207 | - | **Phase 4**: Implementation (execute tasks.md following constitutional principles) | |
| 208 | - | **Phase 5**: Validation (run tests, execute quickstart.md, performance validation) | |
| 209 | - | ||
| 210 | - | ## Complexity Tracking | |
| 211 | - | *Fill ONLY if Constitution Check has violations that must be justified* | |
| 212 | - | ||
| 213 | - | | Violation | Why Needed | Simpler Alternative Rejected Because | | |
| 214 | - | |-----------|------------|-------------------------------------| | |
| 215 | - | | [e.g., 4th project] | [current need] | [why 3 projects insufficient] | | |
| 216 | - | | [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] | | |
| 217 | - | ||
| 218 | - | ||
| 219 | - | ## Progress Tracking | |
| 220 | - | *This checklist is updated during execution flow* | |
| 221 | - | ||
| 222 | - | **Phase Status**: | |
| 223 | - | - [x] Phase 0: Research complete (/plan command) | |
| 224 | - | - [x] Phase 1: Design complete (/plan command) | |
| 225 | - | - [x] Phase 2: Task planning complete (/plan command - describe approach only) | |
| 226 | - | - [ ] Phase 3: Tasks generated (/tasks command) | |
| 227 | - | - [ ] Phase 4: Implementation complete | |
| 228 | - | - [ ] Phase 5: Validation passed | |
| 229 | - | ||
| 230 | - | **Gate Status**: | |
| 231 | - | - [x] Initial Constitution Check: PASS | |
| 232 | - | - [x] Post-Design Constitution Check: PASS | |
| 233 | - | - [x] All NEEDS CLARIFICATION resolved | |
| 234 | - | - [x] Complexity deviations documented (none required) | |
| 235 | - | ||
| 236 | - | --- | |
| 237 | - | *Based on Constitution v2.1.1 - See `/memory/constitution.md`*⏎̸ | |
D specs/002-browser-controls-ui/quickstart.md +0 -184
| @@ -1,184 +0,0 @@ | |||
| 1 | - | # Quickstart: Browser Controls UI | |
| 2 | - | ||
| 3 | - | ## Quick Validation Steps | |
| 4 | - | ||
| 5 | - | ### Prerequisites | |
| 6 | - | - Dumber browser built and running | |
| 7 | - | - SQLite database initialized | |
| 8 | - | - WebView displaying a webpage | |
| 9 | - | - Linux system with clipboard tools (wlcopy/xclip/xsel) | |
| 10 | - | ||
| 11 | - | ### Test Scenario 1: Zoom Controls (FR-001, FR-002, FR-007, FR-008) | |
| 12 | - | **Goal**: Verify zoom in/out functionality with visual feedback | |
| 13 | - | ||
| 14 | - | 1. **Setup**: Navigate to any webpage (e.g., `dumber browse github.com`) | |
| 15 | - | 2. **Test Zoom In**: | |
| 16 | - | - Press `Ctrl` + `+` (plus key) | |
| 17 | - | - **Expected**: Page content becomes larger, visual feedback shown | |
| 18 | - | - **Verify**: Zoom level increases from 100% to 110% | |
| 19 | - | 3. **Test Zoom Out**: | |
| 20 | - | - Press `Ctrl` + `-` (minus key) | |
| 21 | - | - **Expected**: Page content becomes smaller | |
| 22 | - | - **Verify**: Zoom level decreases to 100% | |
| 23 | - | 4. **Test Zoom Limits**: | |
| 24 | - | - Press `Ctrl` + `-` repeatedly until 30% reached | |
| 25 | - | - Press `Ctrl` + `-` again | |
| 26 | - | - **Expected**: No further zoom reduction, remains at 30% | |
| 27 | - | - Repeat for upper limit (500%) | |
| 28 | - | ||
| 29 | - | **Pass Criteria**: ✅ Zoom changes are visible and bounded correctly | |
| 30 | - | ||
| 31 | - | ### Test Scenario 2: Navigation Controls (FR-003, FR-004, FR-010) | |
| 32 | - | **Goal**: Verify mouse back/forward button functionality | |
| 33 | - | ||
| 34 | - | 1. **Setup**: Navigate to multiple pages to build history: | |
| 35 | - | - `dumber browse github.com` | |
| 36 | - | - Navigate to `github.com/bnema` | |
| 37 | - | - Navigate to any repository page | |
| 38 | - | 2. **Test Back Navigation**: | |
| 39 | - | - Click mouse button 4 (back button) | |
| 40 | - | - **Expected**: Browser navigates to previous page | |
| 41 | - | - **Verify**: URL changes to previous page in history | |
| 42 | - | 3. **Test Forward Navigation**: | |
| 43 | - | - Click mouse button 5 (forward button) | |
| 44 | - | - **Expected**: Browser navigates forward in history | |
| 45 | - | - **Verify**: URL changes to next page | |
| 46 | - | 4. **Test Empty History Edge Cases**: | |
| 47 | - | - Navigate back to beginning of history | |
| 48 | - | - Click back button again | |
| 49 | - | - **Expected**: No navigation occurs, no error shown | |
| 50 | - | ||
| 51 | - | **Pass Criteria**: ✅ Navigation works and handles edge cases gracefully | |
| 52 | - | ||
| 53 | - | ### Test Scenario 3: URL Copy (FR-005, FR-006, FR-011) | |
| 54 | - | **Goal**: Verify URL copying with clipboard tool fallbacks | |
| 55 | - | ||
| 56 | - | 1. **Setup**: Ensure at least one clipboard tool is available: | |
| 57 | - | ```bash | |
| 58 | - | which wlcopy || which xclip || which xsel | |
| 59 | - | ``` | |
| 60 | - | 2. **Test URL Copy**: | |
| 61 | - | - Navigate to any webpage | |
| 62 | - | - Press `Ctrl` + `Shift` + `C` | |
| 63 | - | - **Expected**: Current URL copied to clipboard | |
| 64 | - | 3. **Test Clipboard Content**: | |
| 65 | - | ```bash | |
| 66 | - | # Wayland | |
| 67 | - | wl-paste | |
| 68 | - | # X11 | |
| 69 | - | xclip -o -selection clipboard | |
| 70 | - | ``` | |
| 71 | - | - **Verify**: Output matches current browser URL | |
| 72 | - | 4. **Test Fallback Chain** (if multiple tools available): | |
| 73 | - | - Temporarily rename `wlcopy` to test fallback | |
| 74 | - | - Repeat copy operation | |
| 75 | - | - **Expected**: Falls back to `xclip` or `xsel` | |
| 76 | - | ||
| 77 | - | **Pass Criteria**: ✅ URL copying works with proper fallback behavior | |
| 78 | - | ||
| 79 | - | ### Test Scenario 4: Zoom Persistence (FR-009) | |
| 80 | - | **Goal**: Verify per-domain zoom level persistence | |
| 81 | - | ||
| 82 | - | 1. **Setup**: Clear any existing zoom preferences | |
| 83 | - | 2. **Test Domain Persistence**: | |
| 84 | - | - Navigate to `github.com` | |
| 85 | - | - Set zoom to 120% (Ctrl + + twice from 100%) | |
| 86 | - | - Navigate away to `stackoverflow.com` | |
| 87 | - | - Set zoom to 80% (Ctrl + - twice from 100%) | |
| 88 | - | - Navigate back to `github.com` | |
| 89 | - | - **Expected**: Zoom automatically restores to 120% | |
| 90 | - | 3. **Test Session Persistence**: | |
| 91 | - | - Close and restart browser | |
| 92 | - | - Navigate to `github.com` | |
| 93 | - | - **Expected**: Zoom level still at 120% | |
| 94 | - | ||
| 95 | - | **Pass Criteria**: ✅ Zoom levels persist per-domain across sessions | |
| 96 | - | ||
| 97 | - | ### Test Scenario 5: Window Title Updates (FR-012) | |
| 98 | - | **Goal**: Verify dynamic window title updates | |
| 99 | - | ||
| 100 | - | 1. **Setup**: Browser window visible with title bar | |
| 101 | - | 2. **Test Title Updates**: | |
| 102 | - | - Navigate to `github.com` | |
| 103 | - | - **Expected**: Window title shows "Dumber - GitHub" | |
| 104 | - | - Navigate to a specific repository | |
| 105 | - | - **Expected**: Window title updates to show repository name | |
| 106 | - | - Navigate to `stackoverflow.com` | |
| 107 | - | - **Expected**: Window title shows "Dumber - Stack Overflow" | |
| 108 | - | ||
| 109 | - | **Pass Criteria**: ✅ Window title dynamically reflects current page | |
| 110 | - | ||
| 111 | - | ## Integration Test Checklist | |
| 112 | - | ||
| 113 | - | ### Database Integration | |
| 114 | - | - [ ] Zoom levels stored in `zoom_levels` table | |
| 115 | - | - [ ] Domain-based lookups work correctly | |
| 116 | - | - [ ] Old zoom preferences cleaned up periodically | |
| 117 | - | - [ ] Database transactions complete successfully | |
| 118 | - | ||
| 119 | - | ### WebView Integration | |
| 120 | - | - [ ] Keyboard events captured from WebView | |
| 121 | - | - [ ] Mouse events captured and processed | |
| 122 | - | - [ ] CSS zoom applied correctly | |
| 123 | - | - [ ] Navigation history maintained | |
| 124 | - | ||
| 125 | - | ### System Integration | |
| 126 | - | - [ ] Clipboard tools detected correctly | |
| 127 | - | - [ ] Fallback chain executes in order | |
| 128 | - | - [ ] Error handling for missing tools | |
| 129 | - | - [ ] No system dependencies beyond WebKit2GTK | |
| 130 | - | ||
| 131 | - | ## Performance Verification | |
| 132 | - | ||
| 133 | - | ### Response Time Tests | |
| 134 | - | 1. **Zoom Operations**: | |
| 135 | - | - Measure time from keypress to visual change | |
| 136 | - | - **Target**: < 100ms response time | |
| 137 | - | 2. **Navigation Operations**: | |
| 138 | - | - Measure time from mouse click to page load | |
| 139 | - | - **Target**: < 200ms for local history navigation | |
| 140 | - | 3. **Database Operations**: | |
| 141 | - | - Measure zoom level persistence write time | |
| 142 | - | - **Target**: < 50ms for database writes | |
| 143 | - | ||
| 144 | - | ### Memory Usage Tests | |
| 145 | - | 1. **Baseline**: Measure memory before feature use | |
| 146 | - | 2. **After Usage**: Use all features extensively for 10 minutes | |
| 147 | - | 3. **Memory Growth**: Should be < 10MB additional usage | |
| 148 | - | 4. **No Leaks**: Memory should stabilize, not continuously grow | |
| 149 | - | ||
| 150 | - | ## Troubleshooting | |
| 151 | - | ||
| 152 | - | ### Common Issues | |
| 153 | - | 1. **Zoom not working**: Check JavaScript console for errors | |
| 154 | - | 2. **Mouse buttons not responding**: Verify WebView focus state | |
| 155 | - | 3. **Clipboard copy failing**: Check available clipboard tools | |
| 156 | - | 4. **Database errors**: Verify SQLite file permissions | |
| 157 | - | 5. **Title not updating**: Check UpdatePageTitle service calls | |
| 158 | - | ||
| 159 | - | ### Debug Commands | |
| 160 | - | ```bash | |
| 161 | - | # Check clipboard tools | |
| 162 | - | which wlcopy xclip xsel | |
| 163 | - | ||
| 164 | - | # Verify database schema | |
| 165 | - | sqlite3 ~/.config/dumber/browser.db ".schema zoom_levels" | |
| 166 | - | ||
| 167 | - | # Check zoom level data | |
| 168 | - | sqlite3 ~/.config/dumber/browser.db "SELECT * FROM zoom_levels;" | |
| 169 | - | ||
| 170 | - | # Monitor application logs | |
| 171 | - | dumber --debug | |
| 172 | - | ``` | |
| 173 | - | ||
| 174 | - | ## Success Criteria | |
| 175 | - | ||
| 176 | - | All test scenarios must pass with: | |
| 177 | - | - ✅ No crashes or error dialogs | |
| 178 | - | - ✅ Responsive UI (< 100ms feedback) | |
| 179 | - | - ✅ Data persistence working correctly | |
| 180 | - | - ✅ Graceful error handling | |
| 181 | - | - ✅ Cross-platform clipboard compatibility | |
| 182 | - | - ✅ Memory usage within constitutional limits | |
| 183 | - | ||
| 184 | - | **Ready for Production**: All scenarios pass consistently across test runs⏎̸ | |
D specs/002-browser-controls-ui/research.md +0 -133
| @@ -1,133 +0,0 @@ | |||
| 1 | - | # Research: Browser Controls UI | |
| 2 | - | ||
| 3 | - | ## Research Tasks | |
| 4 | - | ||
| 5 | - | ### 1. Wails v3 Keyboard Event Handling | |
| 6 | - | **Task**: Research keyboard event handling in Wails v3-alpha for desktop applications | |
| 7 | - | ||
| 8 | - | **Decision**: Use Wails context menu and event system with JavaScript frontend integration | |
| 9 | - | **Rationale**: | |
| 10 | - | - Wails v3 provides native keyboard event handling through WebView2/WebKit integration | |
| 11 | - | - Frontend JavaScript can capture keyboard events and call backend Go methods via context | |
| 12 | - | - Maintains separation between UI (JavaScript) and business logic (Go services) | |
| 13 | - | - No additional dependencies required beyond existing Wails framework | |
| 14 | - | ||
| 15 | - | **Alternatives considered**: | |
| 16 | - | - Direct GTK keyboard hooks: Rejected due to complexity and Wails abstraction | |
| 17 | - | - OS-level global hotkeys: Rejected as not needed (app-specific shortcuts only) | |
| 18 | - | - Third-party hotkey libraries: Rejected to maintain constitution's simplicity principle | |
| 19 | - | ||
| 20 | - | ### 2. Mouse Button Event Handling (Back/Forward) | |
| 21 | - | **Task**: Research mouse button 4/5 (back/forward) event handling in WebView context | |
| 22 | - | ||
| 23 | - | **Decision**: Use JavaScript mouse event listeners with event.button detection | |
| 24 | - | **Rationale**: | |
| 25 | - | - Standard web platform approach using addEventListener('mousedown') | |
| 26 | - | - event.button === 3 (back) and event.button === 4 (forward) detection | |
| 27 | - | - Works consistently across WebKit2GTK implementations | |
| 28 | - | - No platform-specific code required | |
| 29 | - | ||
| 30 | - | **Alternatives considered**: | |
| 31 | - | - GTK mouse event capture: Rejected due to Wails abstraction layer | |
| 32 | - | - X11/Wayland direct event handling: Rejected as breaks single-binary principle | |
| 33 | - | ||
| 34 | - | ### 3. Zoom Level Management and Persistence | |
| 35 | - | **Task**: Research zoom level implementation patterns and domain-based persistence | |
| 36 | - | ||
| 37 | - | **Decision**: Use WebView zoom API with SQLite domain-based storage | |
| 38 | - | **Rationale**: | |
| 39 | - | - WebView provides native zoom functionality (setZoomFactor) | |
| 40 | - | - Firefox zoom levels provide proven UX pattern (30%-500% range) | |
| 41 | - | - SQLite table for domain → zoom_level mapping enables per-site persistence | |
| 42 | - | - Existing database infrastructure can be extended | |
| 43 | - | ||
| 44 | - | **Alternatives considered**: | |
| 45 | - | - CSS transform scaling: Rejected due to layout issues and non-standard behavior | |
| 46 | - | - Browser-level zoom only: Rejected as doesn't persist per-domain | |
| 47 | - | - Configuration file storage: Rejected as database is faster for lookups | |
| 48 | - | ||
| 49 | - | ### 4. Linux Clipboard Integration (wlcopy fallback chain) | |
| 50 | - | **Task**: Research Linux clipboard tool availability and fallback patterns | |
| 51 | - | ||
| 52 | - | **Decision**: Implement command execution chain: wlcopy → xclip → xsel | |
| 53 | - | **Rationale**: | |
| 54 | - | - wlcopy is Wayland-native (primary target environment) | |
| 55 | - | - xclip and xsel provide X11 compatibility | |
| 56 | - | - exec.Command provides clean abstraction for tool detection | |
| 57 | - | - Graceful degradation maintains usability across Linux variants | |
| 58 | - | ||
| 59 | - | **Alternatives considered**: | |
| 60 | - | - Go clipboard libraries: Rejected due to additional dependencies | |
| 61 | - | - D-Bus clipboard access: Rejected as complex and not universally available | |
| 62 | - | - Only wlcopy support: Rejected as limits platform compatibility | |
| 63 | - | ||
| 64 | - | ### 5. WebView Zoom API Integration | |
| 65 | - | **Task**: Research WebView zoom control APIs in Wails v3 context | |
| 66 | - | ||
| 67 | - | **Decision**: Use frontend JavaScript with backend coordination for zoom state | |
| 68 | - | **Rationale**: | |
| 69 | - | - document.body.style.zoom CSS property for immediate visual feedback | |
| 70 | - | - Backend Go service manages zoom level persistence and bounds checking | |
| 71 | - | - Maintains constitutional separation between UI and business logic | |
| 72 | - | - No direct WebView API dependency required | |
| 73 | - | ||
| 74 | - | **Alternatives considered**: | |
| 75 | - | - Direct WebView SetZoom API: Not available in Wails v3-alpha abstraction | |
| 76 | - | - Pure CSS zoom transforms: Rejected due to layout calculation issues | |
| 77 | - | ||
| 78 | - | ## Key Technical Findings | |
| 79 | - | ||
| 80 | - | ### Firefox Zoom Levels | |
| 81 | - | Standard zoom progression: 30%, 50%, 67%, 80%, 90%, 100%, 110%, 120%, 133%, 150%, 170%, 200%, 240%, 300%, 400%, 500% | |
| 82 | - | ||
| 83 | - | ### Event Handling Architecture | |
| 84 | - | ``` | |
| 85 | - | Frontend (JavaScript) → Wails Context → Backend (Go) → Services → Database | |
| 86 | - | ↑ ↓ | |
| 87 | - | UI Events State Persistence | |
| 88 | - | ``` | |
| 89 | - | ||
| 90 | - | ### Clipboard Tool Detection Pattern | |
| 91 | - | ```go | |
| 92 | - | var clipboardTools = []string{"wlcopy", "xclip", "xsel"} | |
| 93 | - | for _, tool := range clipboardTools { | |
| 94 | - | if _, err := exec.LookPath(tool); err == nil { | |
| 95 | - | // Use this tool | |
| 96 | - | break | |
| 97 | - | } | |
| 98 | - | } | |
| 99 | - | ``` | |
| 100 | - | ||
| 101 | - | ### Database Schema Extension | |
| 102 | - | New table: `zoom_levels` | |
| 103 | - | ```sql | |
| 104 | - | CREATE TABLE zoom_levels ( | |
| 105 | - | domain TEXT PRIMARY KEY, | |
| 106 | - | zoom_factor REAL NOT NULL DEFAULT 1.0, | |
| 107 | - | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| 108 | - | ); | |
| 109 | - | ``` | |
| 110 | - | ||
| 111 | - | ## Risks and Mitigation | |
| 112 | - | ||
| 113 | - | 1. **Risk**: WebView zoom behavior inconsistency across platforms | |
| 114 | - | **Mitigation**: Use CSS zoom with bounds checking, test on target platforms | |
| 115 | - | ||
| 116 | - | 2. **Risk**: Mouse button events not captured in WebView | |
| 117 | - | **Mitigation**: Implement JavaScript event delegation on document level | |
| 118 | - | ||
| 119 | - | 3. **Risk**: Clipboard tools unavailable on target system | |
| 120 | - | **Mitigation**: Graceful degradation with user notification | |
| 121 | - | ||
| 122 | - | 4. **Risk**: Zoom persistence performance impact | |
| 123 | - | **Mitigation**: Debounce zoom level saves, use SQLite prepared statements | |
| 124 | - | ||
| 125 | - | ## Implementation Dependencies | |
| 126 | - | ||
| 127 | - | - No new external dependencies required | |
| 128 | - | - Leverage existing: Wails v3, SQLite, standard Go library | |
| 129 | - | - Frontend JavaScript for event capture | |
| 130 | - | - Backend Go services for state management | |
| 131 | - | - Database schema extension for zoom persistence | |
| 132 | - | ||
| 133 | - | All research findings support constitutional principles of speed, simplicity, and single-binary architecture.⏎̸ | |
D specs/002-browser-controls-ui/spec.md +0 -118
| @@ -1,118 +0,0 @@ | |||
| 1 | - | # Feature Specification: Browser Controls UI | |
| 2 | - | ||
| 3 | - | **Feature Branch**: `002-browser-controls-ui` | |
| 4 | - | **Created**: 2025-09-09 | |
| 5 | - | **Status**: Draft | |
| 6 | - | **Input**: User description: "Browser Controls UI, I want to add button and keyboard controls to the web browser, for now ctrl + to zoom, Ctrl - to unzoom, back/next mouse buttons, and ctrl shift c to copy url into wlcopy" | |
| 7 | - | ||
| 8 | - | ## Execution Flow (main) | |
| 9 | - | ``` | |
| 10 | - | 1. Parse user description from Input | |
| 11 | - | → Feature: Browser navigation and zoom controls with clipboard integration | |
| 12 | - | 2. Extract key concepts from description | |
| 13 | - | → Actors: Browser users | |
| 14 | - | → Actions: Zoom in/out, navigate back/forward, copy URL | |
| 15 | - | → Data: Current page URL, zoom level | |
| 16 | - | → Constraints: Linux clipboard integration (wlcopy) | |
| 17 | - | 3. For each unclear aspect: | |
| 18 | - | → Zoom levels follow Firefox behavior (30%-500%, per-domain persistence) | |
| 19 | - | → Navigation history edge cases handle empty history silently | |
| 20 | - | 4. Fill User Scenarios & Testing section | |
| 21 | - | → User can zoom and navigate using keyboard and mouse | |
| 22 | - | 5. Generate Functional Requirements | |
| 23 | - | → Each requirement focuses on user capabilities | |
| 24 | - | 6. Identify Key Entities | |
| 25 | - | → Browser state (zoom, history, current URL) | |
| 26 | - | 7. Run Review Checklist | |
| 27 | - | → All requirements clarified and specified | |
| 28 | - | 8. Return: SUCCESS (spec ready for planning) | |
| 29 | - | ``` | |
| 30 | - | ||
| 31 | - | --- | |
| 32 | - | ||
| 33 | - | ## ⚡ Quick Guidelines | |
| 34 | - | - ✅ Focus on WHAT users need and WHY | |
| 35 | - | - ❌ Avoid HOW to implement (no tech stack, APIs, code structure) | |
| 36 | - | - 👥 Written for business stakeholders, not developers | |
| 37 | - | ||
| 38 | - | --- | |
| 39 | - | ||
| 40 | - | ## User Scenarios & Testing *(mandatory)* | |
| 41 | - | ||
| 42 | - | ### Primary User Story | |
| 43 | - | A user browsing web content wants to quickly navigate and adjust their viewing experience using familiar keyboard shortcuts and mouse controls. They need to zoom in to read small text, zoom out to see more content, navigate through their browsing history, and easily share the current page URL with others. | |
| 44 | - | ||
| 45 | - | ### Acceptance Scenarios | |
| 46 | - | 1. **Given** the browser is displaying a webpage, **When** the user presses Ctrl+Plus, **Then** the page zooms in and content becomes larger | |
| 47 | - | 2. **Given** the browser is displaying a webpage, **When** the user presses Ctrl+Minus, **Then** the page zooms out and more content becomes visible | |
| 48 | - | 3. **Given** the user has navigated to previous pages, **When** the user clicks the back mouse button, **Then** the browser navigates to the previous page in history | |
| 49 | - | 4. **Given** the user has navigated back in history, **When** the user clicks the forward mouse button, **Then** the browser navigates to the next page in history | |
| 50 | - | 5. **Given** the browser is displaying a webpage, **When** the user presses Ctrl+Shift+C, **Then** the current page URL is copied to the system clipboard via wlcopy | |
| 51 | - | ||
| 52 | - | ### Edge Cases | |
| 53 | - | - What happens when user tries to zoom beyond 30% or 500% limits? (System ignores further zoom attempts) | |
| 54 | - | - How does system handle zoom keyboard shortcuts when no page is loaded? (System applies zoom to next loaded page) | |
| 55 | - | - What happens when back/forward mouse buttons are pressed but no history exists? (System does nothing/ignores silently) | |
| 56 | - | - How does system handle clipboard copy when wlcopy command is not available? (System tries fallback: xclip → xsel) | |
| 57 | - | ||
| 58 | - | ## Requirements *(mandatory)* | |
| 59 | - | ||
| 60 | - | ### Functional Requirements | |
| 61 | - | - **FR-001**: System MUST respond to Ctrl+Plus keyboard shortcut to zoom in the current webpage | |
| 62 | - | - **FR-002**: System MUST respond to Ctrl+Minus keyboard shortcut to zoom out the current webpage | |
| 63 | - | - **FR-003**: System MUST respond to back mouse button clicks to navigate to previous page in browsing history | |
| 64 | - | - **FR-004**: System MUST respond to forward mouse button clicks to navigate to next page in browsing history | |
| 65 | - | - **FR-005**: System MUST respond to Ctrl+Shift+C keyboard shortcut to copy current page URL to system clipboard | |
| 66 | - | - **FR-006**: System MUST integrate with wlcopy command for clipboard operations on Linux systems | |
| 67 | - | - **FR-007**: System MUST provide visual feedback when zoom level changes | |
| 68 | - | - **FR-008**: System MUST implement Firefox-style zoom levels (30%, 50%, 67%, 80%, 90%, 100%, 110%, 120%, 133%, 150%, 170%, 200%, 240%, 300%, 400%, 500%) | |
| 69 | - | - **FR-009**: System MUST persist zoom levels per-domain between browser sessions | |
| 70 | - | - **FR-011**: System MUST attempt clipboard fallback sequence (wlcopy → xclip → xsel) when primary clipboard tool fails | |
| 71 | - | - **FR-010**: System MUST handle cases where navigation history is empty (disable/ignore navigation attempts) | |
| 72 | - | - **FR-012**: System MUST update window title dynamically when page title changes (format: "Dumber - [Page Title]") | |
| 73 | - | ||
| 74 | - | ### Key Entities *(include if feature involves data)* | |
| 75 | - | - **Browser State**: Represents current browsing context including zoom level, navigation history, and active URL | |
| 76 | - | - **Navigation History**: Collection of previously visited pages enabling back/forward functionality | |
| 77 | - | - **Zoom Level**: Current magnification setting for webpage display | |
| 78 | - | ||
| 79 | - | --- | |
| 80 | - | ||
| 81 | - | ## Review & Acceptance Checklist | |
| 82 | - | *GATE: Automated checks run during main() execution* | |
| 83 | - | ||
| 84 | - | ### Content Quality | |
| 85 | - | - [x] No implementation details (languages, frameworks, APIs) | |
| 86 | - | - [x] Focused on user value and business needs | |
| 87 | - | - [x] Written for non-technical stakeholders | |
| 88 | - | - [x] All mandatory sections completed | |
| 89 | - | ||
| 90 | - | ### Requirement Completeness | |
| 91 | - | - [x] No [NEEDS CLARIFICATION] markers remain | |
| 92 | - | - [x] Requirements are testable and unambiguous | |
| 93 | - | - [x] Success criteria are measurable | |
| 94 | - | - [x] Scope is clearly bounded | |
| 95 | - | - [x] Dependencies and assumptions identified | |
| 96 | - | ||
| 97 | - | --- | |
| 98 | - | ||
| 99 | - | ## Execution Status | |
| 100 | - | *Updated by main() during processing* | |
| 101 | - | ||
| 102 | - | - [x] User description parsed | |
| 103 | - | - [x] Key concepts extracted | |
| 104 | - | - [x] Ambiguities marked | |
| 105 | - | - [x] User scenarios defined | |
| 106 | - | - [x] Requirements generated | |
| 107 | - | - [x] Entities identified | |
| 108 | - | - [x] Review checklist passed | |
| 109 | - | ||
| 110 | - | --- | |
| 111 | - | ||
| 112 | - | ## Implementation Notes | |
| 113 | - | ||
| 114 | - | ### Frontend Integration Requirements | |
| 115 | - | - The frontend needs to call `UpdatePageTitle` when the page loads to trigger the title update. This can be done via JavaScript when the page finishes loading. | |
| 116 | - | - Window title format: "Dumber - [Page Title]" (e.g., "Dumber - Google", "Dumber - Wikipedia") | |
| 117 | - | ||
| 118 | - | ---⏎̸ | |
D specs/002-browser-controls-ui/tasks.md +0 -186
| @@ -1,186 +0,0 @@ | |||
| 1 | - | # Tasks: Browser Controls UI | |
| 2 | - | ||
| 3 | - | **Input**: Design documents from `/home/brice/dev/projects/dumb-browser/specs/002-browser-controls-ui/` | |
| 4 | - | **Prerequisites**: plan.md, research.md, data-model.md, contracts/browser-controls-api.yaml | |
| 5 | - | ||
| 6 | - | ## Feature Summary | |
| 7 | - | Implement keyboard and mouse navigation controls for the Wails-based browser: zoom in/out with Ctrl+/-, back/forward navigation with mouse buttons, URL copying with Ctrl+Shift+C, and dynamic window title updates with SQLite persistence. | |
| 8 | - | ||
| 9 | - | ## Path Conventions | |
| 10 | - | Single project structure (desktop application): | |
| 11 | - | - **Source**: `src/models/`, `src/services/`, `src/cli/`, `src/lib/` | |
| 12 | - | - **Tests**: `tests/contract/`, `tests/integration/`, `tests/unit/` | |
| 13 | - | - **Frontend**: `frontend/src/` | |
| 14 | - | - **Database**: SQLite with SQLC generated queries | |
| 15 | - | ||
| 16 | - | ## Phase 3.1: Setup | |
| 17 | - | ||
| 18 | - | - [ ] T001 Create zoom_levels database table with SQLite schema migration in `src/db/migrations/003_add_zoom_levels.sql` | |
| 19 | - | - [ ] T002 Generate SQLC queries for zoom level operations in `src/db/queries/zoom_levels.sql` | |
| 20 | - | - [ ] T003 [P] Add frontend JavaScript event handlers in `frontend/src/events/keyboard.js` | |
| 21 | - | - [ ] T004 [P] Add frontend mouse event handlers in `frontend/src/events/mouse.js` | |
| 22 | - | ||
| 23 | - | ## Phase 3.2: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.3 | |
| 24 | - | ||
| 25 | - | **CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation** | |
| 26 | - | ||
| 27 | - | ### Contract Tests [P] | |
| 28 | - | - [ ] T005 [P] Contract test POST /zoom/in endpoint in `tests/contract/zoom_in_test.go` | |
| 29 | - | - [ ] T006 [P] Contract test POST /zoom/out endpoint in `tests/contract/zoom_out_test.go` | |
| 30 | - | - [ ] T007 [P] Contract test POST /navigation/back endpoint in `tests/contract/navigation_back_test.go` | |
| 31 | - | - [ ] T008 [P] Contract test POST /navigation/forward endpoint in `tests/contract/navigation_forward_test.go` | |
| 32 | - | - [ ] T009 [P] Contract test POST /clipboard/copy-url endpoint in `tests/contract/clipboard_copy_test.go` | |
| 33 | - | - [ ] T010 [P] Contract test GET /zoom/get-level endpoint in `tests/contract/zoom_get_test.go` | |
| 34 | - | ||
| 35 | - | ### Integration Tests [P] | |
| 36 | - | - [ ] T011 [P] Integration test zoom persistence across domains in `tests/integration/zoom_persistence_test.go` | |
| 37 | - | - [ ] T012 [P] Integration test keyboard event handling in `tests/integration/keyboard_events_test.go` | |
| 38 | - | - [ ] T013 [P] Integration test mouse navigation in `tests/integration/mouse_navigation_test.go` | |
| 39 | - | - [ ] T014 [P] Integration test clipboard tool fallback chain in `tests/integration/clipboard_fallback_test.go` | |
| 40 | - | - [ ] T015 [P] Integration test window title updates in `tests/integration/window_title_test.go` | |
| 41 | - | ||
| 42 | - | ## Phase 3.3: Core Implementation (ONLY after tests are failing) | |
| 43 | - | ||
| 44 | - | ### Data Models [P] | |
| 45 | - | - [ ] T016 [P] ZoomLevel model with validation in `src/models/zoom_level.go` | |
| 46 | - | - [ ] T017 [P] BrowserState model extensions in `src/models/browser_state.go` | |
| 47 | - | - [ ] T018 [P] KeyboardEvent model for event processing in `src/models/keyboard_event.go` | |
| 48 | - | - [ ] T019 [P] MouseEvent model for navigation in `src/models/mouse_event.go` | |
| 49 | - | ||
| 50 | - | ### Core Services [P] | |
| 51 | - | - [ ] T020 [P] ZoomService with Firefox zoom levels in `src/services/zoom_service.go` | |
| 52 | - | - [ ] T021 [P] NavigationService with history management in `src/services/navigation_service.go` | |
| 53 | - | - [ ] T022 [P] ClipboardService with tool fallback in `src/services/clipboard_service.go` | |
| 54 | - | - [ ] T023 [P] WindowTitleService for dynamic updates in `src/services/window_title_service.go` | |
| 55 | - | ||
| 56 | - | ### Wails Service Layer | |
| 57 | - | - [ ] T024 BrowserControlService main service in `src/services/browser_control_service.go` | |
| 58 | - | - [ ] T025 ZoomIn method implementation with domain persistence | |
| 59 | - | - [ ] T026 ZoomOut method implementation with bounds checking | |
| 60 | - | - [ ] T027 NavigateBack method with history validation | |
| 61 | - | - [ ] T028 NavigateForward method with forward history | |
| 62 | - | - [ ] T029 CopyCurrentURL method with clipboard tool detection | |
| 63 | - | - [ ] T030 GetZoomLevel method for domain lookup | |
| 64 | - | ||
| 65 | - | ### Database Layer | |
| 66 | - | - [ ] T031 ZoomLevelRepository with SQLC integration in `src/repositories/zoom_level_repository.go` | |
| 67 | - | - [ ] T032 Database transaction management for zoom operations | |
| 68 | - | - [ ] T033 Cleanup job for old zoom level entries | |
| 69 | - | ||
| 70 | - | ## Phase 3.4: Integration | |
| 71 | - | ||
| 72 | - | ### Frontend Integration | |
| 73 | - | - [ ] T034 Wire keyboard events to Wails backend calls in `frontend/src/events/keyboard.js` | |
| 74 | - | - [ ] T035 Wire mouse events to navigation methods in `frontend/src/events/mouse.js` | |
| 75 | - | - [ ] T036 CSS zoom application with visual feedback in `frontend/src/styles/zoom.css` | |
| 76 | - | - [ ] T037 Window title update integration with page changes | |
| 77 | - | ||
| 78 | - | ### Backend Integration | |
| 79 | - | - [ ] T038 Register BrowserControlService with Wails context in `src/app.go` | |
| 80 | - | - [ ] T039 Database migration execution on startup | |
| 81 | - | - [ ] T040 Error handling and logging for all service methods | |
| 82 | - | - [ ] T041 Service method validation and bounds checking | |
| 83 | - | ||
| 84 | - | ## Phase 3.5: Polish | |
| 85 | - | ||
| 86 | - | ### Unit Tests [P] | |
| 87 | - | - [ ] T042 [P] Unit tests for Firefox zoom level validation in `tests/unit/zoom_levels_test.go` | |
| 88 | - | - [ ] T043 [P] Unit tests for clipboard tool detection in `tests/unit/clipboard_tools_test.go` | |
| 89 | - | - [ ] T044 [P] Unit tests for navigation history bounds in `tests/unit/navigation_bounds_test.go` | |
| 90 | - | - [ ] T045 [P] Unit tests for domain validation in `tests/unit/domain_validation_test.go` | |
| 91 | - | ||
| 92 | - | ### Performance & Documentation | |
| 93 | - | - [ ] T046 Performance test: zoom operations < 100ms response in `tests/performance/zoom_perf_test.go` | |
| 94 | - | - [ ] T047 Performance test: navigation < 200ms response in `tests/performance/nav_perf_test.go` | |
| 95 | - | - [ ] T048 Memory usage test: < 10MB additional usage over 10 minutes | |
| 96 | - | - [ ] T049 Update README with new keyboard shortcuts and features | |
| 97 | - | - [ ] T050 Run quickstart.md validation scenarios | |
| 98 | - | ||
| 99 | - | ## Dependencies | |
| 100 | - | ||
| 101 | - | **Critical Dependencies:** | |
| 102 | - | - Database setup (T001-T002) blocks all repository tasks (T031-T033) | |
| 103 | - | - All tests (T005-T015) MUST complete and FAIL before implementation (T016-T041) | |
| 104 | - | - Models (T016-T019) block services (T020-T023) | |
| 105 | - | - Services block Wails integration (T024-T030) | |
| 106 | - | - Core implementation blocks frontend integration (T034-T041) | |
| 107 | - | ||
| 108 | - | **Parallel Groups:** | |
| 109 | - | - Setup frontend events: T003, T004 | |
| 110 | - | - Contract tests: T005-T010 | |
| 111 | - | - Integration tests: T011-T015 | |
| 112 | - | - Data models: T016-T019 | |
| 113 | - | - Core services: T020-T023 | |
| 114 | - | - Unit tests: T042-T045 | |
| 115 | - | ||
| 116 | - | ## Parallel Execution Examples | |
| 117 | - | ||
| 118 | - | ```bash | |
| 119 | - | # Phase 3.1 Setup (parallel frontend) | |
| 120 | - | Task: "Add frontend JavaScript event handlers in frontend/src/events/keyboard.js" | |
| 121 | - | Task: "Add frontend mouse event handlers in frontend/src/events/mouse.js" | |
| 122 | - | ||
| 123 | - | # Phase 3.2 Contract Tests (all parallel) | |
| 124 | - | Task: "Contract test POST /zoom/in endpoint in tests/contract/zoom_in_test.go" | |
| 125 | - | Task: "Contract test POST /zoom/out endpoint in tests/contract/zoom_out_test.go" | |
| 126 | - | Task: "Contract test POST /navigation/back endpoint in tests/contract/navigation_back_test.go" | |
| 127 | - | Task: "Contract test POST /navigation/forward endpoint in tests/contract/navigation_forward_test.go" | |
| 128 | - | Task: "Contract test POST /clipboard/copy-url endpoint in tests/contract/clipboard_copy_test.go" | |
| 129 | - | Task: "Contract test GET /zoom/get-level endpoint in tests/contract/zoom_get_test.go" | |
| 130 | - | ||
| 131 | - | # Phase 3.2 Integration Tests (all parallel) | |
| 132 | - | Task: "Integration test zoom persistence across domains in tests/integration/zoom_persistence_test.go" | |
| 133 | - | Task: "Integration test keyboard event handling in tests/integration/keyboard_events_test.go" | |
| 134 | - | Task: "Integration test mouse navigation in tests/integration/mouse_navigation_test.go" | |
| 135 | - | Task: "Integration test clipboard tool fallback chain in tests/integration/clipboard_fallback_test.go" | |
| 136 | - | Task: "Integration test window title updates in tests/integration/window_title_test.go" | |
| 137 | - | ||
| 138 | - | # Phase 3.3 Data Models (all parallel) | |
| 139 | - | Task: "ZoomLevel model with validation in src/models/zoom_level.go" | |
| 140 | - | Task: "BrowserState model extensions in src/models/browser_state.go" | |
| 141 | - | Task: "KeyboardEvent model for event processing in src/models/keyboard_event.go" | |
| 142 | - | Task: "MouseEvent model for navigation in src/models/mouse_event.go" | |
| 143 | - | ||
| 144 | - | # Phase 3.3 Core Services (all parallel) | |
| 145 | - | Task: "ZoomService with Firefox zoom levels in src/services/zoom_service.go" | |
| 146 | - | Task: "NavigationService with history management in src/services/navigation_service.go" | |
| 147 | - | Task: "ClipboardService with tool fallback in src/services/clipboard_service.go" | |
| 148 | - | Task: "WindowTitleService for dynamic updates in src/services/window_title_service.go" | |
| 149 | - | ``` | |
| 150 | - | ||
| 151 | - | ## Firefox Zoom Levels Reference | |
| 152 | - | Standard zoom progression: 30%, 50%, 67%, 80%, 90%, 100%, 110%, 120%, 133%, 150%, 170%, 200%, 240%, 300%, 400%, 500% | |
| 153 | - | ||
| 154 | - | ## Clipboard Tool Fallback Chain | |
| 155 | - | 1. `wlcopy` (Wayland native) | |
| 156 | - | 2. `xclip` (X11 primary) | |
| 157 | - | 3. `xsel` (X11 fallback) | |
| 158 | - | ||
| 159 | - | ## Database Schema | |
| 160 | - | ```sql | |
| 161 | - | CREATE TABLE zoom_levels ( | |
| 162 | - | domain TEXT PRIMARY KEY, | |
| 163 | - | zoom_factor REAL NOT NULL DEFAULT 1.0 CHECK(zoom_factor >= 0.3 AND zoom_factor <= 5.0), | |
| 164 | - | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| 165 | - | ); | |
| 166 | - | CREATE INDEX idx_zoom_levels_updated_at ON zoom_levels(updated_at); | |
| 167 | - | ``` | |
| 168 | - | ||
| 169 | - | ## Validation Checklist | |
| 170 | - | - [x] All contracts have corresponding tests (T005-T010) | |
| 171 | - | - [x] All entities have model tasks (T016-T019) | |
| 172 | - | - [x] All tests come before implementation (Phase 3.2 before 3.3) | |
| 173 | - | - [x] Parallel tasks truly independent (different files) | |
| 174 | - | - [x] Each task specifies exact file path | |
| 175 | - | - [x] No task modifies same file as another [P] task | |
| 176 | - | ||
| 177 | - | ## Success Criteria | |
| 178 | - | - All quickstart.md test scenarios pass | |
| 179 | - | - Performance targets met (< 100ms zoom, < 200ms navigation) | |
| 180 | - | - Memory usage within constitutional limits (< 10MB additional) | |
| 181 | - | - Cross-platform clipboard compatibility maintained | |
| 182 | - | - No regressions in existing browser functionality | |
| 183 | - | ||
| 184 | - | **Total Tasks**: 50 tasks across 5 phases | |
| 185 | - | **Estimated Completion**: 2-3 days with parallel execution | |
| 186 | - | **Critical Path**: Database setup → Tests → Models → Services → Integration⏎̸ | |
D specs/003-webkit2gtk-migration/contracts/webkit-bindings-api.yaml +0 -279
| @@ -1,279 +0,0 @@ | |||
| 1 | - | openapi: 3.0.3 | |
| 2 | - | info: | |
| 3 | - | title: WebKit2GTK Go Bindings API | |
| 4 | - | description: Contract for pkg/webkit Go bindings to WebKit2GTK native browser engine | |
| 5 | - | version: 1.0.0 | |
| 6 | - | contact: | |
| 7 | - | name: Dumber Browser WebKit Integration | |
| 8 | - | ||
| 9 | - | paths: | |
| 10 | - | # Note: This is a native library API, not REST endpoints | |
| 11 | - | # These represent Go function signatures for contract testing | |
| 12 | - | ||
| 13 | - | components: | |
| 14 | - | schemas: | |
| 15 | - | WebViewConfig: | |
| 16 | - | type: object | |
| 17 | - | properties: | |
| 18 | - | width: | |
| 19 | - | type: integer | |
| 20 | - | minimum: 800 | |
| 21 | - | description: Initial window width | |
| 22 | - | height: | |
| 23 | - | type: integer | |
| 24 | - | minimum: 600 | |
| 25 | - | description: Initial window height | |
| 26 | - | userAgent: | |
| 27 | - | type: string | |
| 28 | - | description: Browser user agent string | |
| 29 | - | enableDevTools: | |
| 30 | - | type: boolean | |
| 31 | - | default: true | |
| 32 | - | description: Enable WebKit developer tools | |
| 33 | - | enableJavaScript: | |
| 34 | - | type: boolean | |
| 35 | - | default: true | |
| 36 | - | description: Enable JavaScript execution | |
| 37 | - | required: | |
| 38 | - | - width | |
| 39 | - | - height | |
| 40 | - | ||
| 41 | - | NavigationRequest: | |
| 42 | - | type: object | |
| 43 | - | properties: | |
| 44 | - | url: | |
| 45 | - | type: string | |
| 46 | - | format: uri | |
| 47 | - | description: Target URL for navigation | |
| 48 | - | timeout: | |
| 49 | - | type: integer | |
| 50 | - | default: 30000 | |
| 51 | - | description: Navigation timeout in milliseconds | |
| 52 | - | required: | |
| 53 | - | - url | |
| 54 | - | ||
| 55 | - | NavigationResult: | |
| 56 | - | type: object | |
| 57 | - | properties: | |
| 58 | - | success: | |
| 59 | - | type: boolean | |
| 60 | - | description: Navigation success status | |
| 61 | - | finalURL: | |
| 62 | - | type: string | |
| 63 | - | format: uri | |
| 64 | - | description: Final URL after redirects | |
| 65 | - | loadTime: | |
| 66 | - | type: integer | |
| 67 | - | description: Page load time in milliseconds | |
| 68 | - | error: | |
| 69 | - | type: string | |
| 70 | - | nullable: true | |
| 71 | - | description: Error message if navigation failed | |
| 72 | - | ||
| 73 | - | KeyboardShortcut: | |
| 74 | - | type: object | |
| 75 | - | properties: | |
| 76 | - | modifiers: | |
| 77 | - | type: array | |
| 78 | - | items: | |
| 79 | - | type: string | |
| 80 | - | enum: [ctrl, alt, shift, cmd] | |
| 81 | - | description: Modifier keys required | |
| 82 | - | key: | |
| 83 | - | type: string | |
| 84 | - | description: Primary key (e.g., 'c', 'Left', 'Right') | |
| 85 | - | action: | |
| 86 | - | type: string | |
| 87 | - | enum: [navigate_back, navigate_forward, copy_url, zoom_in, zoom_out, zoom_reset] | |
| 88 | - | description: Action to perform | |
| 89 | - | required: | |
| 90 | - | - key | |
| 91 | - | - action | |
| 92 | - | ||
| 93 | - | ScriptInjectionRequest: | |
| 94 | - | type: object | |
| 95 | - | properties: | |
| 96 | - | script: | |
| 97 | - | type: string | |
| 98 | - | description: JavaScript code to inject | |
| 99 | - | runAtEnd: | |
| 100 | - | type: boolean | |
| 101 | - | default: false | |
| 102 | - | description: Run script after DOM content loaded | |
| 103 | - | worldName: | |
| 104 | - | type: string | |
| 105 | - | default: "dumber-browser" | |
| 106 | - | description: WebKit user script world name | |
| 107 | - | required: | |
| 108 | - | - script | |
| 109 | - | ||
| 110 | - | ScriptInjectionResult: | |
| 111 | - | type: object | |
| 112 | - | properties: | |
| 113 | - | success: | |
| 114 | - | type: boolean | |
| 115 | - | description: Script injection success status | |
| 116 | - | error: | |
| 117 | - | type: string | |
| 118 | - | nullable: true | |
| 119 | - | description: Error message if injection failed | |
| 120 | - | ||
| 121 | - | ZoomRequest: | |
| 122 | - | type: object | |
| 123 | - | properties: | |
| 124 | - | level: | |
| 125 | - | type: number | |
| 126 | - | minimum: 0.25 | |
| 127 | - | maximum: 5.0 | |
| 128 | - | description: Zoom level (1.0 = 100%) | |
| 129 | - | required: | |
| 130 | - | - level | |
| 131 | - | ||
| 132 | - | ZoomResult: | |
| 133 | - | type: object | |
| 134 | - | properties: | |
| 135 | - | success: | |
| 136 | - | type: boolean | |
| 137 | - | description: Zoom operation success status | |
| 138 | - | actualLevel: | |
| 139 | - | type: number | |
| 140 | - | description: Actual zoom level set by WebKit | |
| 141 | - | error: | |
| 142 | - | type: string | |
| 143 | - | nullable: true | |
| 144 | - | description: Error message if zoom failed | |
| 145 | - | ||
| 146 | - | BrowserError: | |
| 147 | - | type: object | |
| 148 | - | properties: | |
| 149 | - | code: | |
| 150 | - | type: string | |
| 151 | - | enum: [ | |
| 152 | - | WEBKIT_INIT_FAILED, | |
| 153 | - | GTK_INIT_FAILED, | |
| 154 | - | NAVIGATION_FAILED, | |
| 155 | - | SCRIPT_INJECTION_FAILED, | |
| 156 | - | KEYBOARD_BINDING_FAILED, | |
| 157 | - | MEMORY_LIMIT_EXCEEDED | |
| 158 | - | ] | |
| 159 | - | message: | |
| 160 | - | type: string | |
| 161 | - | description: Human-readable error message | |
| 162 | - | details: | |
| 163 | - | type: string | |
| 164 | - | nullable: true | |
| 165 | - | description: Technical error details | |
| 166 | - | required: | |
| 167 | - | - code | |
| 168 | - | - message | |
| 169 | - | ||
| 170 | - | # Contract Test Functions (Go function signatures) | |
| 171 | - | # These will be implemented as integration tests | |
| 172 | - | ||
| 173 | - | x-go-functions: | |
| 174 | - | ||
| 175 | - | # WebView Management | |
| 176 | - | NewWebView: | |
| 177 | - | description: Create new WebKit browser instance | |
| 178 | - | parameters: | |
| 179 | - | - name: config | |
| 180 | - | schema: WebViewConfig | |
| 181 | - | returns: | |
| 182 | - | - name: webview | |
| 183 | - | type: "*WebView" | |
| 184 | - | - name: error | |
| 185 | - | type: error | |
| 186 | - | ||
| 187 | - | LoadURL: | |
| 188 | - | description: Navigate to specified URL | |
| 189 | - | parameters: | |
| 190 | - | - name: webview | |
| 191 | - | type: "*WebView" | |
| 192 | - | - name: request | |
| 193 | - | schema: NavigationRequest | |
| 194 | - | returns: | |
| 195 | - | - name: result | |
| 196 | - | schema: NavigationResult | |
| 197 | - | - name: error | |
| 198 | - | type: error | |
| 199 | - | ||
| 200 | - | # Keyboard Shortcuts | |
| 201 | - | RegisterKeyboardShortcut: | |
| 202 | - | description: Register keyboard shortcut handler | |
| 203 | - | parameters: | |
| 204 | - | - name: webview | |
| 205 | - | type: "*WebView" | |
| 206 | - | - name: shortcut | |
| 207 | - | schema: KeyboardShortcut | |
| 208 | - | - name: callback | |
| 209 | - | type: "func()" | |
| 210 | - | returns: | |
| 211 | - | - name: error | |
| 212 | - | type: error | |
| 213 | - | ||
| 214 | - | # Script Injection | |
| 215 | - | InjectScript: | |
| 216 | - | description: Inject JavaScript into current page | |
| 217 | - | parameters: | |
| 218 | - | - name: webview | |
| 219 | - | type: "*WebView" | |
| 220 | - | - name: request | |
| 221 | - | schema: ScriptInjectionRequest | |
| 222 | - | returns: | |
| 223 | - | - name: result | |
| 224 | - | schema: ScriptInjectionResult | |
| 225 | - | - name: error | |
| 226 | - | type: error | |
| 227 | - | ||
| 228 | - | # Zoom Control | |
| 229 | - | SetZoom: | |
| 230 | - | description: Set browser zoom level | |
| 231 | - | parameters: | |
| 232 | - | - name: webview | |
| 233 | - | type: "*WebView" | |
| 234 | - | - name: request | |
| 235 | - | schema: ZoomRequest | |
| 236 | - | returns: | |
| 237 | - | - name: result | |
| 238 | - | schema: ZoomResult | |
| 239 | - | - name: error | |
| 240 | - | type: error | |
| 241 | - | ||
| 242 | - | GetZoom: | |
| 243 | - | description: Get current browser zoom level | |
| 244 | - | parameters: | |
| 245 | - | - name: webview | |
| 246 | - | type: "*WebView" | |
| 247 | - | returns: | |
| 248 | - | - name: level | |
| 249 | - | type: float64 | |
| 250 | - | - name: error | |
| 251 | - | type: error | |
| 252 | - | ||
| 253 | - | # Lifecycle Management | |
| 254 | - | Show: | |
| 255 | - | description: Display browser window | |
| 256 | - | parameters: | |
| 257 | - | - name: webview | |
| 258 | - | type: "*WebView" | |
| 259 | - | returns: | |
| 260 | - | - name: error | |
| 261 | - | type: error | |
| 262 | - | ||
| 263 | - | Hide: | |
| 264 | - | description: Hide browser window | |
| 265 | - | parameters: | |
| 266 | - | - name: webview | |
| 267 | - | type: "*WebView" | |
| 268 | - | returns: | |
| 269 | - | - name: error | |
| 270 | - | type: error | |
| 271 | - | ||
| 272 | - | Destroy: | |
| 273 | - | description: Clean up browser resources | |
| 274 | - | parameters: | |
| 275 | - | - name: webview | |
| 276 | - | type: "*WebView" | |
| 277 | - | returns: | |
| 278 | - | - name: error | |
| 279 | - | type: error⏎̸ | |
D specs/003-webkit2gtk-migration/data-model.md +0 -155
| @@ -1,155 +0,0 @@ | |||
| 1 | - | # Data Model: WebKit2GTK Native Browser Backend | |
| 2 | - | ||
| 3 | - | **Feature**: Native WebKit Browser Backend | |
| 4 | - | **Date**: 2025-01-21 | |
| 5 | - | **Status**: Complete | |
| 6 | - | ||
| 7 | - | ## Core Entities | |
| 8 | - | ||
| 9 | - | ### WebKit Browser Instance | |
| 10 | - | **Purpose**: Main browser engine wrapper managing WebKitWebView and GTK window | |
| 11 | - | **Key Attributes**: | |
| 12 | - | - WebView: WebKitWebView instance for rendering | |
| 13 | - | - Window: GTK ApplicationWindow container | |
| 14 | - | - Settings: WebKitSettings for browser configuration | |
| 15 | - | - UserContentManager: WebKitUserContentManager for JavaScript injection | |
| 16 | - | - KeybindingController: GTK event handler for keyboard shortcuts | |
| 17 | - | ||
| 18 | - | **Relationships**: | |
| 19 | - | - Contains one WebKitWebView instance | |
| 20 | - | - Manages one GTK ApplicationWindow | |
| 21 | - | - References shared HistoryManager and ZoomManager | |
| 22 | - | - Interfaces with existing SQLite database through unchanged schema | |
| 23 | - | ||
| 24 | - | ### WebKit Bindings Interface | |
| 25 | - | **Purpose**: CGO wrapper providing Go interface to WebKit2GTK C APIs | |
| 26 | - | **Key Attributes**: | |
| 27 | - | - WebViewHandle: C pointer to WebKitWebView | |
| 28 | - | - WindowHandle: C pointer to GtkApplicationWindow | |
| 29 | - | - SettingsHandle: C pointer to WebKitSettings | |
| 30 | - | - CallbackRegistry: Go callback functions for WebKit signals | |
| 31 | - | - ErrorContext: Error propagation from C to Go | |
| 32 | - | ||
| 33 | - | **State Transitions**: | |
| 34 | - | 1. Uninitialized → C library loaded → GTK initialized → WebKit configured → Ready | |
| 35 | - | 2. Ready → Loading URL → Content loaded → Interactive | |
| 36 | - | 3. Interactive → Navigation event → Loading URL (cycle) | |
| 37 | - | 4. Any state → Error → Error handling → Recovery attempt | |
| 38 | - | ||
| 39 | - | ### Migration State Manager | |
| 40 | - | **Purpose**: Manages transition from Wails to WebKit implementation | |
| 41 | - | **Key Attributes**: | |
| 42 | - | - MigrationMode: Flag indicating Wails/WebKit/Dual mode | |
| 43 | - | - DataPreservation: User data backup and restore mechanisms | |
| 44 | - | - FeatureParity: Validation checklist for Wails feature equivalence | |
| 45 | - | - PerformanceMetrics: Comparison data between implementations | |
| 46 | - | ||
| 47 | - | **Validation Rules**: | |
| 48 | - | - All existing user data must be preserved during migration | |
| 49 | - | - Browser functionality must maintain 100% feature parity | |
| 50 | - | - Performance must meet or exceed Wails baseline metrics | |
| 51 | - | - Keyboard shortcuts must function identically to current implementation | |
| 52 | - | ||
| 53 | - | ## Data Flow Architecture | |
| 54 | - | ||
| 55 | - | ### Browser Lifecycle | |
| 56 | - | ``` | |
| 57 | - | 1. Application Start | |
| 58 | - | ├── Load pkg/webkit bindings | |
| 59 | - | ├── Initialize GTK application | |
| 60 | - | ├── Create WebKitWebView instance | |
| 61 | - | ├── Configure browser settings | |
| 62 | - | ├── Setup keyboard event handlers | |
| 63 | - | └── Load initial URL or homepage | |
| 64 | - | ||
| 65 | - | 2. URL Navigation | |
| 66 | - | ├── Validate URL through existing parser service | |
| 67 | - | ├── Load URL in WebKitWebView | |
| 68 | - | ├── Update history database (unchanged schema) | |
| 69 | - | ├── Configure zoom level from database | |
| 70 | - | └── Inject global keyboard scripts via UserContentManager | |
| 71 | - | ||
| 72 | - | 3. Keyboard Events | |
| 73 | - | ├── GTK captures key events | |
| 74 | - | ├── Route to appropriate handler (navigation/zoom/copy) | |
| 75 | - | ├── Execute WebKit operation or JavaScript injection | |
| 76 | - | └── Update database if needed (zoom persistence) | |
| 77 | - | ``` | |
| 78 | - | ||
| 79 | - | ### C/Go Interface Boundaries | |
| 80 | - | ``` | |
| 81 | - | Go Layer (pkg/webkit): | |
| 82 | - | ├── WebView struct with Go methods | |
| 83 | - | ├── Event handling with Go channels | |
| 84 | - | ├── Error handling with Go error types | |
| 85 | - | └── Memory management with Go finalizers | |
| 86 | - | ||
| 87 | - | CGO Bridge: | |
| 88 | - | ├── C function wrappers for WebKit APIs | |
| 89 | - | ├── Callback function registration | |
| 90 | - | ├── Memory allocation/deallocation | |
| 91 | - | └── Type conversion (C ↔ Go) | |
| 92 | - | ||
| 93 | - | C Layer (WebKit2GTK): | |
| 94 | - | ├── WebKitWebView widget management | |
| 95 | - | ├── GTK event loop integration | |
| 96 | - | ├── WebKit signals and callbacks | |
| 97 | - | └── Native browser engine operations | |
| 98 | - | ``` | |
| 99 | - | ||
| 100 | - | ## Database Integration | |
| 101 | - | ||
| 102 | - | ### Preserved Schema | |
| 103 | - | **Status**: No changes to existing SQLite schema | |
| 104 | - | - History table: Maintain current structure and data | |
| 105 | - | - Zoom settings table: Continue using domain-based zoom storage | |
| 106 | - | - All SQLC generated queries: Unchanged interface | |
| 107 | - | - Database migrations: No new migrations required | |
| 108 | - | ||
| 109 | - | ### New Database Interactions | |
| 110 | - | **WebKit-specific data**: Store as configuration, not database entities | |
| 111 | - | - WebKit settings: Managed through WebKitSettings API | |
| 112 | - | - User content scripts: Stored as embedded resources, not database | |
| 113 | - | - Browser state: Memory-only, restored through WebKit APIs | |
| 114 | - | ||
| 115 | - | ## Error Handling Model | |
| 116 | - | ||
| 117 | - | ### Error Propagation Chain | |
| 118 | - | ``` | |
| 119 | - | WebKit C Error → CGO Error Conversion → Go Error → User Notification | |
| 120 | - | ||
| 121 | - | Error Categories: | |
| 122 | - | ├── Initialization Errors: WebKit library loading, GTK setup | |
| 123 | - | ├── Navigation Errors: Invalid URLs, network failures, load timeouts | |
| 124 | - | ├── Script Injection Errors: UserContentManager failures, CSP violations | |
| 125 | - | ├── Keyboard Binding Errors: GTK event registration, handler failures | |
| 126 | - | └── Performance Errors: Memory limits, CPU constraints, timeout violations | |
| 127 | - | ``` | |
| 128 | - | ||
| 129 | - | ### Recovery Strategies | |
| 130 | - | - Initialization failures: Fallback error dialog, graceful exit | |
| 131 | - | - Navigation errors: Error page display, retry mechanisms | |
| 132 | - | - Script failures: Silent failure with logging, functionality degradation | |
| 133 | - | - Memory errors: Garbage collection, resource cleanup, restart recommendation | |
| 134 | - | ||
| 135 | - | ## Performance Data Model | |
| 136 | - | ||
| 137 | - | ### Metrics Collection | |
| 138 | - | **Startup Performance**: | |
| 139 | - | - Library loading time: WebKit2GTK and GTK initialization | |
| 140 | - | - WebView creation time: Widget setup and configuration | |
| 141 | - | - First paint time: Initial browser window display | |
| 142 | - | ||
| 143 | - | **Runtime Performance**: | |
| 144 | - | - Memory usage: WebKit process + GTK overhead + Go runtime | |
| 145 | - | - Navigation speed: URL load time, DOM ready time | |
| 146 | - | - Event handling latency: Keyboard shortcut response time | |
| 147 | - | ||
| 148 | - | **Comparison Baseline**: | |
| 149 | - | - Current Wails metrics as performance targets | |
| 150 | - | - Performance regression detection through automated testing | |
| 151 | - | - Resource usage monitoring for constitutional compliance (<100MB baseline) | |
| 152 | - | ||
| 153 | - | --- | |
| 154 | - | ||
| 155 | - | **Data Model Status**: ✅ Complete - All entities defined, ready for contract generation⏎̸ | |
D specs/003-webkit2gtk-migration/plan.md +0 -240
| @@ -1,240 +0,0 @@ | |||
| 1 | - | # Implementation Plan: Native WebKit Browser Backend | |
| 2 | - | ||
| 3 | - | **Branch**: `003-webkit2gtk-migration` | **Date**: 2025-01-21 | **Spec**: [spec.md](spec.md) | |
| 4 | - | **Input**: Feature specification from `/home/brice/dev/projects/dumb-browser/specs/003-webkit2gtk-migration/spec.md` | |
| 5 | - | ||
| 6 | - | ## Execution Flow (/plan command scope) | |
| 7 | - | ``` | |
| 8 | - | 1. Load feature spec from Input path | |
| 9 | - | → If not found: ERROR "No feature spec at {path}" | |
| 10 | - | 2. Fill Technical Context (scan for NEEDS CLARIFICATION) | |
| 11 | - | → Detect Project Type from context (web=frontend+backend, mobile=app+api) | |
| 12 | - | → Set Structure Decision based on project type | |
| 13 | - | 3. Evaluate Constitution Check section below | |
| 14 | - | → If violations exist: Document in Complexity Tracking | |
| 15 | - | → If no justification possible: ERROR "Simplify approach first" | |
| 16 | - | → Update Progress Tracking: Initial Constitution Check | |
| 17 | - | 4. Execute Phase 0 → research.md | |
| 18 | - | → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns" | |
| 19 | - | 5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI). | |
| 20 | - | 6. Re-evaluate Constitution Check section | |
| 21 | - | → If new violations: Refactor design, return to Phase 1 | |
| 22 | - | → Update Progress Tracking: Post-Design Constitution Check | |
| 23 | - | 7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) | |
| 24 | - | 8. STOP - Ready for /tasks command | |
| 25 | - | ``` | |
| 26 | - | ||
| 27 | - | **IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands: | |
| 28 | - | - Phase 2: /tasks command creates tasks.md | |
| 29 | - | - Phase 3-4: Implementation execution (manual or via tools) | |
| 30 | - | ||
| 31 | - | ## Summary | |
| 32 | - | Replace Wails framework with direct WebKit2GTK bindings to gain full control over browser engine capabilities, maintain all existing functionality while removing framework limitations, and create custom C Go bindings in a pkg/ package for potential future extraction. | |
| 33 | - | ||
| 34 | - | ## Technical Context | |
| 35 | - | **Language/Version**: Go 1.25.1 + C bindings for WebKit2GTK | |
| 36 | - | **Primary Dependencies**: WebKit2GTK, GTK3, CGO for C bindings | |
| 37 | - | **Storage**: SQLite (maintain existing database schema and data) | |
| 38 | - | **Testing**: Go testing + WebKit integration tests | |
| 39 | - | **Target Platform**: Linux (Wayland/X11) - focus on GTK-based systems | |
| 40 | - | **Project Type**: single - native desktop application | |
| 41 | - | **Performance Goals**: <500ms startup time, <100MB baseline memory, maintain existing performance | |
| 42 | - | **Constraints**: Remove all Wails dependencies, preserve user data, maintain keyboard shortcuts and browser features | |
| 43 | - | **Scale/Scope**: Single browser window, existing CLI functionality, WebKit2GTK reference clone for development | |
| 44 | - | ||
| 45 | - | ## Constitution Check | |
| 46 | - | *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | |
| 47 | - | ||
| 48 | - | **Simplicity**: | |
| 49 | - | - Projects: 1 (single native browser application) | |
| 50 | - | - Using framework directly? ✅ (Direct WebKit2GTK, removing Wails wrapper) | |
| 51 | - | - Single data model? ✅ (Maintain existing SQLite schema) | |
| 52 | - | - Avoiding patterns? ✅ (Direct C bindings, no unnecessary abstraction layers) | |
| 53 | - | ||
| 54 | - | **Architecture**: | |
| 55 | - | - EVERY feature as library? ✅ (pkg/ package for WebKit bindings, reusable) | |
| 56 | - | - Libraries listed: pkg/webkit (WebKit2GTK Go bindings), existing internal packages | |
| 57 | - | - CLI per library: Maintain existing CLI, add webkit package testing commands | |
| 58 | - | - Library docs: llms.txt format planned for pkg/webkit | |
| 59 | - | ||
| 60 | - | **Testing (NON-NEGOTIABLE)**: | |
| 61 | - | - RED-GREEN-Refactor cycle enforced? ✅ (Contract tests for WebKit bindings first) | |
| 62 | - | - Git commits show tests before implementation? ✅ (Will create failing WebKit tests) | |
| 63 | - | - Order: Contract→Integration→E2E→Unit strictly followed? ✅ | |
| 64 | - | - Real dependencies used? ✅ (Real WebKit2GTK, actual browser engine) | |
| 65 | - | - Integration tests for: WebKit bindings, browser functionality, keyboard shortcuts | |
| 66 | - | - FORBIDDEN: Implementation before test, skipping RED phase | |
| 67 | - | ||
| 68 | - | **Observability**: | |
| 69 | - | - Structured logging included? ✅ (Continue using slog) | |
| 70 | - | - Frontend logs → backend? ✅ (WebKit console logs to Go backend) | |
| 71 | - | - Error context sufficient? ✅ (WebKit error propagation to Go) | |
| 72 | - | ||
| 73 | - | **Versioning**: | |
| 74 | - | - Version number assigned? Next version after current (maintain semver) | |
| 75 | - | - BUILD increments on every change? ✅ | |
| 76 | - | - Breaking changes handled? ✅ (Migration from Wails to native, preserve user data) | |
| 77 | - | ||
| 78 | - | ## Project Structure | |
| 79 | - | ||
| 80 | - | ### Documentation (this feature) | |
| 81 | - | ``` | |
| 82 | - | specs/[###-feature]/ | |
| 83 | - | ├── plan.md # This file (/plan command output) | |
| 84 | - | ├── research.md # Phase 0 output (/plan command) | |
| 85 | - | ├── data-model.md # Phase 1 output (/plan command) | |
| 86 | - | ├── quickstart.md # Phase 1 output (/plan command) | |
| 87 | - | ├── contracts/ # Phase 1 output (/plan command) | |
| 88 | - | └── tasks.md # Phase 2 output (/tasks command - NOT created by /plan) | |
| 89 | - | ``` | |
| 90 | - | ||
| 91 | - | ### Source Code (repository root) | |
| 92 | - | ``` | |
| 93 | - | # Option 1: Single project (DEFAULT) | |
| 94 | - | src/ | |
| 95 | - | ├── models/ | |
| 96 | - | ├── services/ | |
| 97 | - | ├── cli/ | |
| 98 | - | └── lib/ | |
| 99 | - | ||
| 100 | - | tests/ | |
| 101 | - | ├── contract/ | |
| 102 | - | ├── integration/ | |
| 103 | - | └── unit/ | |
| 104 | - | ||
| 105 | - | # Option 2: Web application (when "frontend" + "backend" detected) | |
| 106 | - | backend/ | |
| 107 | - | ├── src/ | |
| 108 | - | │ ├── models/ | |
| 109 | - | │ ├── services/ | |
| 110 | - | │ └── api/ | |
| 111 | - | └── tests/ | |
| 112 | - | ||
| 113 | - | frontend/ | |
| 114 | - | ├── src/ | |
| 115 | - | │ ├── components/ | |
| 116 | - | │ ├── pages/ | |
| 117 | - | │ └── services/ | |
| 118 | - | └── tests/ | |
| 119 | - | ||
| 120 | - | # Option 3: Mobile + API (when "iOS/Android" detected) | |
| 121 | - | api/ | |
| 122 | - | └── [same as backend above] | |
| 123 | - | ||
| 124 | - | ios/ or android/ | |
| 125 | - | └── [platform-specific structure] | |
| 126 | - | ``` | |
| 127 | - | ||
| 128 | - | **Structure Decision**: Option 1 (Single project) - Native desktop application with pkg/ for WebKit bindings | |
| 129 | - | ||
| 130 | - | ## Phase 0: Outline & Research | |
| 131 | - | 1. **Extract unknowns from Technical Context** above: | |
| 132 | - | - For each NEEDS CLARIFICATION → research task | |
| 133 | - | - For each dependency → best practices task | |
| 134 | - | - For each integration → patterns task | |
| 135 | - | ||
| 136 | - | 2. **Generate and dispatch research agents**: | |
| 137 | - | ``` | |
| 138 | - | For each unknown in Technical Context: | |
| 139 | - | Task: "Research {unknown} for {feature context}" | |
| 140 | - | For each technology choice: | |
| 141 | - | Task: "Find best practices for {tech} in {domain}" | |
| 142 | - | ``` | |
| 143 | - | ||
| 144 | - | 3. **Consolidate findings** in `research.md` using format: | |
| 145 | - | - Decision: [what was chosen] | |
| 146 | - | - Rationale: [why chosen] | |
| 147 | - | - Alternatives considered: [what else evaluated] | |
| 148 | - | ||
| 149 | - | **Output**: research.md with all NEEDS CLARIFICATION resolved | |
| 150 | - | ||
| 151 | - | ## Phase 1: Design & Contracts | |
| 152 | - | *Prerequisites: research.md complete* | |
| 153 | - | ||
| 154 | - | 1. **Extract entities from feature spec** → `data-model.md`: | |
| 155 | - | - Entity name, fields, relationships | |
| 156 | - | - Validation rules from requirements | |
| 157 | - | - State transitions if applicable | |
| 158 | - | ||
| 159 | - | 2. **Generate API contracts** from functional requirements: | |
| 160 | - | - For each user action → endpoint | |
| 161 | - | - Use standard REST/GraphQL patterns | |
| 162 | - | - Output OpenAPI/GraphQL schema to `/contracts/` | |
| 163 | - | ||
| 164 | - | 3. **Generate contract tests** from contracts: | |
| 165 | - | - One test file per endpoint | |
| 166 | - | - Assert request/response schemas | |
| 167 | - | - Tests must fail (no implementation yet) | |
| 168 | - | ||
| 169 | - | 4. **Extract test scenarios** from user stories: | |
| 170 | - | - Each story → integration test scenario | |
| 171 | - | - Quickstart test = story validation steps | |
| 172 | - | ||
| 173 | - | 5. **Update agent file incrementally** (O(1) operation): | |
| 174 | - | - Run `/scripts/update-agent-context.sh [claude|gemini|copilot]` for your AI assistant | |
| 175 | - | - If exists: Add only NEW tech from current plan | |
| 176 | - | - Preserve manual additions between markers | |
| 177 | - | - Update recent changes (keep last 3) | |
| 178 | - | - Keep under 150 lines for token efficiency | |
| 179 | - | - Output to repository root | |
| 180 | - | ||
| 181 | - | **Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file | |
| 182 | - | ||
| 183 | - | ## Phase 2: Task Planning Approach | |
| 184 | - | *This section describes what the /tasks command will do - DO NOT execute during /plan* | |
| 185 | - | ||
| 186 | - | **Task Generation Strategy**: | |
| 187 | - | - Load `/templates/tasks-template.md` as base | |
| 188 | - | - Generate tasks from WebKit bindings contract (webkit-bindings-api.yaml) | |
| 189 | - | - Create pkg/webkit package structure and CGO bridge tasks [P] | |
| 190 | - | - WebKit2GTK reference repository setup and analysis tasks | |
| 191 | - | - Contract tests for each WebKit API function [P] | |
| 192 | - | - Integration tests for browser features (navigation, zoom, shortcuts) | |
| 193 | - | - Migration tasks to remove Wails dependencies sequentially | |
| 194 | - | - Performance validation and data preservation verification tasks | |
| 195 | - | ||
| 196 | - | **Ordering Strategy**: | |
| 197 | - | - TDD order: Contract tests before WebKit bindings implementation | |
| 198 | - | - Dependency order: CGO bridge → WebKit API → Browser integration → Wails removal | |
| 199 | - | - Parallel tasks: Independent WebKit functions, separate test files [P] | |
| 200 | - | - Sequential migration: Preserve existing functionality throughout transition | |
| 201 | - | ||
| 202 | - | **Estimated Output**: 30-35 numbered, ordered tasks focusing on WebKit migration in tasks.md | |
| 203 | - | ||
| 204 | - | **IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan | |
| 205 | - | ||
| 206 | - | ## Phase 3+: Future Implementation | |
| 207 | - | *These phases are beyond the scope of the /plan command* | |
| 208 | - | ||
| 209 | - | **Phase 3**: Task execution (/tasks command creates tasks.md) | |
| 210 | - | **Phase 4**: Implementation (execute tasks.md following constitutional principles) | |
| 211 | - | **Phase 5**: Validation (run tests, execute quickstart.md, performance validation) | |
| 212 | - | ||
| 213 | - | ## Complexity Tracking | |
| 214 | - | *Fill ONLY if Constitution Check has violations that must be justified* | |
| 215 | - | ||
| 216 | - | | Violation | Why Needed | Simpler Alternative Rejected Because | | |
| 217 | - | |-----------|------------|-------------------------------------| | |
| 218 | - | | [e.g., 4th project] | [current need] | [why 3 projects insufficient] | | |
| 219 | - | | [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] | | |
| 220 | - | ||
| 221 | - | ||
| 222 | - | ## Progress Tracking | |
| 223 | - | *This checklist is updated during execution flow* | |
| 224 | - | ||
| 225 | - | **Phase Status**: | |
| 226 | - | - [x] Phase 0: Research complete (/plan command) | |
| 227 | - | - [x] Phase 1: Design complete (/plan command) | |
| 228 | - | - [x] Phase 2: Task planning complete (/plan command - describe approach only) | |
| 229 | - | - [ ] Phase 3: Tasks generated (/tasks command) | |
| 230 | - | - [ ] Phase 4: Implementation complete | |
| 231 | - | - [ ] Phase 5: Validation passed | |
| 232 | - | ||
| 233 | - | **Gate Status**: | |
| 234 | - | - [x] Initial Constitution Check: PASS | |
| 235 | - | - [x] Post-Design Constitution Check: PASS | |
| 236 | - | - [x] All NEEDS CLARIFICATION resolved | |
| 237 | - | - [x] Complexity deviations documented (none required) | |
| 238 | - | ||
| 239 | - | --- | |
| 240 | - | *Based on Constitution v2.1.1 - See `/memory/constitution.md`*⏎̸ | |
D specs/003-webkit2gtk-migration/quickstart.md +0 -199
| @@ -1,199 +0,0 @@ | |||
| 1 | - | # Quickstart: WebKit2GTK Native Browser Backend | |
| 2 | - | ||
| 3 | - | **Feature**: Native WebKit Browser Backend | |
| 4 | - | **Date**: 2025-01-21 | |
| 5 | - | **Status**: Ready for implementation | |
| 6 | - | ||
| 7 | - | ## Prerequisites | |
| 8 | - | ||
| 9 | - | ### System Dependencies | |
| 10 | - | ```bash | |
| 11 | - | # Install WebKit2GTK development libraries | |
| 12 | - | sudo pacman -S webkit2gtk-4.0 gtk3 | |
| 13 | - | ||
| 14 | - | # Clone WebKit2GTK reference repository | |
| 15 | - | mkdir -p /home/brice/dev/clone | |
| 16 | - | cd /home/brice/dev/clone | |
| 17 | - | git clone https://github.com/WebKit/webkit.git webkit2gtk-reference | |
| 18 | - | ||
| 19 | - | # Verify CGO is available | |
| 20 | - | go env CGO_ENABLED # Should output: 1 | |
| 21 | - | ``` | |
| 22 | - | ||
| 23 | - | ### Development Environment | |
| 24 | - | ```bash | |
| 25 | - | # Ensure Go version compatibility | |
| 26 | - | go version # Should be Go 1.21+ | |
| 27 | - | ||
| 28 | - | # Install WebKit2GTK pkg-config | |
| 29 | - | pkg-config --cflags webkit2gtk-4.0 # Should output compiler flags | |
| 30 | - | pkg-config --libs webkit2gtk-4.0 # Should output linker flags | |
| 31 | - | ``` | |
| 32 | - | ||
| 33 | - | ## Quick Validation | |
| 34 | - | ||
| 35 | - | ### Step 1: Verify Current State | |
| 36 | - | ```bash | |
| 37 | - | # Check current browser works with Wails | |
| 38 | - | ./dumber-browser | |
| 39 | - | # Expected: Browser opens with homepage, keyboard shortcuts work | |
| 40 | - | ||
| 41 | - | # Note current performance baseline | |
| 42 | - | time ./dumber-browser & | |
| 43 | - | # Expected: Browser starts within 500ms | |
| 44 | - | ``` | |
| 45 | - | ||
| 46 | - | ### Step 2: Basic WebKit Integration Test | |
| 47 | - | ```bash | |
| 48 | - | # Create minimal WebKit test (after pkg/webkit implementation) | |
| 49 | - | cd tests/integration | |
| 50 | - | go test -v ./webkit_basic_test.go | |
| 51 | - | # Expected: WebView creates, loads google.fr, closes cleanly | |
| 52 | - | ``` | |
| 53 | - | ||
| 54 | - | ### Step 3: Feature Parity Validation | |
| 55 | - | ```bash | |
| 56 | - | # Test keyboard shortcuts | |
| 57 | - | # Expected: Alt+Left/Right = navigation, Ctrl+Shift+C = copy URL | |
| 58 | - | ||
| 59 | - | # Test zoom functionality | |
| 60 | - | # Expected: Ctrl++/Ctrl+-/Ctrl+0 zoom in/out/reset | |
| 61 | - | ||
| 62 | - | # Test script injection | |
| 63 | - | # Expected: Global keyboard shortcuts work on external sites | |
| 64 | - | ``` | |
| 65 | - | ||
| 66 | - | ### Step 4: Performance Validation | |
| 67 | - | ```bash | |
| 68 | - | # Startup time test | |
| 69 | - | time ./dumber-browser & | |
| 70 | - | # Target: <500ms (same as Wails baseline) | |
| 71 | - | ||
| 72 | - | # Memory usage test | |
| 73 | - | ps aux | grep dumber-browser | |
| 74 | - | # Target: <100MB baseline + WebKit overhead | |
| 75 | - | ||
| 76 | - | # Navigation performance | |
| 77 | - | # Target: Page loads equivalent to current Wails performance | |
| 78 | - | ``` | |
| 79 | - | ||
| 80 | - | ### Step 5: Data Preservation Test | |
| 81 | - | ```bash | |
| 82 | - | # Backup current database | |
| 83 | - | cp ~/.config/dumber/browser.db ~/.config/dumber/browser.db.backup | |
| 84 | - | ||
| 85 | - | # Run WebKit version, browse some sites, adjust zoom | |
| 86 | - | # Close browser, restart | |
| 87 | - | ||
| 88 | - | # Verify data preserved | |
| 89 | - | sqlite3 ~/.config/dumber/browser.db "SELECT COUNT(*) FROM history;" | |
| 90 | - | # Expected: Same or increased count, no data loss | |
| 91 | - | ||
| 92 | - | # Verify zoom settings preserved | |
| 93 | - | # Expected: Previously set zoom levels maintained | |
| 94 | - | ``` | |
| 95 | - | ||
| 96 | - | ## Success Criteria Checklist | |
| 97 | - | ||
| 98 | - | ### Basic Functionality ✓ | |
| 99 | - | - [ ] Browser window opens and displays correctly | |
| 100 | - | - [ ] Can navigate to google.fr successfully | |
| 101 | - | - [ ] Page renders with full HTML5/CSS3/JavaScript support | |
| 102 | - | - [ ] Browser window closes cleanly without errors | |
| 103 | - | ||
| 104 | - | ### Keyboard Shortcuts ✓ | |
| 105 | - | - [ ] Alt+Left arrow navigates back | |
| 106 | - | - [ ] Alt+Right arrow navigates forward | |
| 107 | - | - [ ] Ctrl+Shift+C copies current URL to clipboard | |
| 108 | - | - [ ] Ctrl+Plus/Equals zooms in | |
| 109 | - | - [ ] Ctrl+Minus zooms out | |
| 110 | - | - [ ] Ctrl+0 resets zoom to 100% | |
| 111 | - | ||
| 112 | - | ### Data Preservation ✓ | |
| 113 | - | - [ ] Existing browser history maintained | |
| 114 | - | - [ ] Zoom settings per domain preserved | |
| 115 | - | - [ ] No database schema changes required | |
| 116 | - | - [ ] All SQLC queries work without modification | |
| 117 | - | ||
| 118 | - | ### Performance Standards ✓ | |
| 119 | - | - [ ] Startup time <500ms (constitution requirement) | |
| 120 | - | - [ ] Memory usage <100MB baseline (constitution requirement) | |
| 121 | - | - [ ] Navigation speed equivalent to Wails baseline | |
| 122 | - | - [ ] Keyboard shortcut response time <100ms | |
| 123 | - | ||
| 124 | - | ### Advanced Features ✓ | |
| 125 | - | - [ ] JavaScript injection works on external sites | |
| 126 | - | - [ ] Developer tools accessible (F12) | |
| 127 | - | - [ ] Error handling graceful (no crashes) | |
| 128 | - | - [ ] Multiple page navigation works correctly | |
| 129 | - | ||
| 130 | - | ## Troubleshooting Common Issues | |
| 131 | - | ||
| 132 | - | ### WebKit Initialization Fails | |
| 133 | - | ```bash | |
| 134 | - | # Check WebKit2GTK installation | |
| 135 | - | pkg-config --exists webkit2gtk-4.0 && echo "WebKit2GTK found" || echo "WebKit2GTK missing" | |
| 136 | - | ||
| 137 | - | # Check GTK installation | |
| 138 | - | pkg-config --exists gtk+-3.0 && echo "GTK3 found" || echo "GTK3 missing" | |
| 139 | - | ``` | |
| 140 | - | ||
| 141 | - | ### CGO Compilation Errors | |
| 142 | - | ```bash | |
| 143 | - | # Verify CGO configuration | |
| 144 | - | go env CGO_ENABLED CGO_CFLAGS CGO_LDFLAGS | |
| 145 | - | ||
| 146 | - | # Test basic CGO compilation | |
| 147 | - | echo 'package main; import "C"; func main() {}' | go run -x - | |
| 148 | - | ``` | |
| 149 | - | ||
| 150 | - | ### Performance Regression | |
| 151 | - | ```bash | |
| 152 | - | # Compare memory usage | |
| 153 | - | # Wails version: ps aux | grep dumber-browser (baseline) | |
| 154 | - | # WebKit version: ps aux | grep dumber-browser (should be similar) | |
| 155 | - | ||
| 156 | - | # Compare startup time | |
| 157 | - | time ./dumber-browser-wails & | |
| 158 | - | time ./dumber-browser-webkit & | |
| 159 | - | # WebKit should be equal or faster | |
| 160 | - | ``` | |
| 161 | - | ||
| 162 | - | ### Keyboard Shortcuts Not Working | |
| 163 | - | ```bash | |
| 164 | - | # Test GTK event handling in isolation | |
| 165 | - | # Check that GTK application receives key events | |
| 166 | - | # Verify WebKit UserContentManager script injection | |
| 167 | - | ||
| 168 | - | # Test on different sites | |
| 169 | - | # google.fr - should work | |
| 170 | - | # Local file - should work | |
| 171 | - | # HTTPS site with CSP - may need handling | |
| 172 | - | ``` | |
| 173 | - | ||
| 174 | - | ## Migration Strategy | |
| 175 | - | ||
| 176 | - | ### Phase 1: Parallel Implementation | |
| 177 | - | - Keep existing Wails code intact | |
| 178 | - | - Develop pkg/webkit alongside current implementation | |
| 179 | - | - Use feature flags or separate binary for testing | |
| 180 | - | ||
| 181 | - | ### Phase 2: Feature Parity | |
| 182 | - | - Achieve 100% functional equivalence with Wails version | |
| 183 | - | - Pass all existing tests with WebKit implementation | |
| 184 | - | - Validate performance meets constitutional requirements | |
| 185 | - | ||
| 186 | - | ### Phase 3: Full Migration | |
| 187 | - | - Switch default implementation to WebKit | |
| 188 | - | - Remove Wails dependencies from go.mod | |
| 189 | - | - Remove frontend TypeScript build system | |
| 190 | - | - Update documentation to remove Wails references | |
| 191 | - | ||
| 192 | - | ### Phase 4: Cleanup | |
| 193 | - | - Remove deprecated Wails code | |
| 194 | - | - Optimize pkg/webkit for production use | |
| 195 | - | - Prepare pkg/webkit for potential repository extraction | |
| 196 | - | ||
| 197 | - | --- | |
| 198 | - | ||
| 199 | - | **Quickstart Status**: ✅ Ready - All validation steps defined, implementation can begin⏎̸ | |
D specs/003-webkit2gtk-migration/research.md +0 -113
| @@ -1,113 +0,0 @@ | |||
| 1 | - | # Research: WebKit2GTK Native Bindings Migration | |
| 2 | - | ||
| 3 | - | **Feature**: Native WebKit Browser Backend | |
| 4 | - | **Date**: 2025-01-21 | |
| 5 | - | **Status**: Complete | |
| 6 | - | ||
| 7 | - | ## WebKit2GTK Integration Patterns | |
| 8 | - | ||
| 9 | - | ### Decision: CGO-based WebKit2GTK bindings | |
| 10 | - | **Rationale**: | |
| 11 | - | - Direct access to WebKit2GTK C APIs provides full control over browser engine | |
| 12 | - | - CGO allows seamless integration of C libraries with Go code | |
| 13 | - | - Performance critical for <500ms startup requirement | |
| 14 | - | - Maintains compatibility with existing GTK-based Linux desktop environments | |
| 15 | - | ||
| 16 | - | **Alternatives considered**: | |
| 17 | - | - Keeping Wails: Rejected due to framework limitations and lack of direct engine control | |
| 18 | - | - gotk3/webkit2: Existing Go bindings but lack modern WebKit2GTK features needed | |
| 19 | - | - Embedding Chromium: Too heavyweight, violates constitution's speed-first principle | |
| 20 | - | ||
| 21 | - | ## C Go Bindings Architecture | |
| 22 | - | ||
| 23 | - | ### Decision: pkg/webkit package structure | |
| 24 | - | **Rationale**: | |
| 25 | - | - Isolates WebKit-specific code for future extraction as separate repository | |
| 26 | - | - Follows Go package conventions with clear API boundaries | |
| 27 | - | - Enables independent testing and versioning of WebKit bindings | |
| 28 | - | - Supports constitution requirement for library-based architecture | |
| 29 | - | ||
| 30 | - | **Alternatives considered**: | |
| 31 | - | - Internal package only: Rejected, doesn't support future repo extraction goal | |
| 32 | - | - Multiple WebKit packages: Over-engineering, violates simplicity principle | |
| 33 | - | - Direct main package integration: Tight coupling, harder to test and maintain | |
| 34 | - | ||
| 35 | - | ## WebKit2GTK Reference Implementation | |
| 36 | - | ||
| 37 | - | ### Decision: Clone WebKit2GTK repository to /home/brice/dev/clone | |
| 38 | - | **Rationale**: | |
| 39 | - | - Provides official API documentation and examples for C bindings | |
| 40 | - | - Reference implementations for browser features (navigation, zoom, JS execution) | |
| 41 | - | - Understanding WebKit widget lifecycle and event handling patterns | |
| 42 | - | - Source of truth for WebKit signal/callback patterns needed for keyboard shortcuts | |
| 43 | - | ||
| 44 | - | **Research findings**: | |
| 45 | - | - WebKit2GTK provides WebKitWebView widget for rendering | |
| 46 | - | - WebKitSettings for browser configuration and feature toggles | |
| 47 | - | - WebKitUserContentManager for JavaScript injection (replaces current Wails script injection) | |
| 48 | - | - GTK key binding system for keyboard shortcuts (Alt+arrows, Ctrl+shortcuts) | |
| 49 | - | ||
| 50 | - | ## Migration Strategy | |
| 51 | - | ||
| 52 | - | ### Decision: Gradual replacement maintaining data compatibility | |
| 53 | - | **Rationale**: | |
| 54 | - | - Constitution requires preserving user data (history, bookmarks, zoom settings) | |
| 55 | - | - Existing SQLite schema and SQLC generated code can be maintained | |
| 56 | - | - Allows A/B testing of WebKit vs Wails implementations | |
| 57 | - | - Minimizes user disruption during migration | |
| 58 | - | ||
| 59 | - | **Migration approach**: | |
| 60 | - | 1. Create pkg/webkit with basic WebView rendering | |
| 61 | - | 2. Implement keyboard shortcuts through GTK event handling | |
| 62 | - | 3. Replace Wails window with GTK ApplicationWindow + WebKitWebView | |
| 63 | - | 4. Migrate script injection from Wails ExecJS to WebKit UserContentManager | |
| 64 | - | 5. Remove Wails dependencies and frontend build system | |
| 65 | - | ||
| 66 | - | ## Performance Considerations | |
| 67 | - | ||
| 68 | - | ### Decision: Direct WebKit widget integration | |
| 69 | - | **Rationale**: | |
| 70 | - | - WebKit2GTK designed for embedding in native applications | |
| 71 | - | - Eliminates JavaScript bridge overhead present in Wails | |
| 72 | - | - Direct GTK event loop integration for better responsiveness | |
| 73 | - | - Memory management handled by GObject reference counting | |
| 74 | - | ||
| 75 | - | **Performance expectations**: | |
| 76 | - | - Startup time improvement due to removing Wails initialization overhead | |
| 77 | - | - Memory reduction by eliminating embedded web frontend | |
| 78 | - | - Better keyboard shortcut responsiveness through direct GTK events | |
| 79 | - | - Improved page loading performance with direct WebKit configuration | |
| 80 | - | ||
| 81 | - | ## Documentation Sources | |
| 82 | - | ||
| 83 | - | ### Decision: Multi-source documentation approach | |
| 84 | - | **Rationale**: | |
| 85 | - | - WebKit2GTK official docs: API reference and C examples | |
| 86 | - | - GNOME Web (Epiphany) source: Real-world WebKit2GTK usage patterns | |
| 87 | - | - CGO best practices: Memory management and C/Go interface design | |
| 88 | - | - GTK documentation: Window management and keyboard event handling | |
| 89 | - | ||
| 90 | - | **Key resources identified**: | |
| 91 | - | - WebKit2GTK API Reference: https://webkitgtk.org/reference/webkit2gtk/stable/ | |
| 92 | - | - Epiphany browser source: Example of WebKit2GTK browser implementation | |
| 93 | - | - CGO documentation: Memory safety and performance best practices | |
| 94 | - | - GTK4 migration guides: Future-proofing for eventual GTK4 support | |
| 95 | - | ||
| 96 | - | ## Risk Mitigation | |
| 97 | - | ||
| 98 | - | ### Decision: Incremental implementation with fallback plan | |
| 99 | - | **Rationale**: | |
| 100 | - | - Large architectural change requires careful validation | |
| 101 | - | - User data preservation is non-negotiable requirement | |
| 102 | - | - Performance regressions would violate constitution speed-first principle | |
| 103 | - | ||
| 104 | - | **Mitigation strategies**: | |
| 105 | - | - Maintain parallel Wails implementation during development | |
| 106 | - | - Comprehensive integration testing before removing Wails | |
| 107 | - | - Database migration scripts with rollback capability | |
| 108 | - | - Performance benchmarking against current Wails implementation | |
| 109 | - | - Feature parity validation through existing test suite | |
| 110 | - | ||
| 111 | - | --- | |
| 112 | - | ||
| 113 | - | **Research Status**: ✅ Complete - All technical unknowns resolved, ready for Phase 1 design⏎̸ | |
D specs/003-webkit2gtk-migration/spec.md +0 -121
| @@ -1,121 +0,0 @@ | |||
| 1 | - | # Feature Specification: Native WebKit Browser Backend | |
| 2 | - | ||
| 3 | - | **Feature Branch**: `003-webkit2gtk-migration` | |
| 4 | - | **Created**: 2025-01-21 | |
| 5 | - | **Status**: Draft | |
| 6 | - | **Input**: User description: "I want to ditch Wails and use Webkit2Gtk directly and create my own C go bindings" | |
| 7 | - | ||
| 8 | - | ## Execution Flow (main) | |
| 9 | - | ``` | |
| 10 | - | 1. Parse user description from Input | |
| 11 | - | → If empty: ERROR "No feature description provided" | |
| 12 | - | 2. Extract key concepts from description | |
| 13 | - | → Identify: actors, actions, data, constraints | |
| 14 | - | 3. For each unclear aspect: | |
| 15 | - | → Mark with [NEEDS CLARIFICATION: specific question] | |
| 16 | - | 4. Fill User Scenarios & Testing section | |
| 17 | - | → If no clear user flow: ERROR "Cannot determine user scenarios" | |
| 18 | - | 5. Generate Functional Requirements | |
| 19 | - | → Each requirement must be testable | |
| 20 | - | → Mark ambiguous requirements | |
| 21 | - | 6. Identify Key Entities (if data involved) | |
| 22 | - | 7. Run Review Checklist | |
| 23 | - | → If any [NEEDS CLARIFICATION]: WARN "Spec has uncertainties" | |
| 24 | - | → If implementation details found: ERROR "Remove tech details" | |
| 25 | - | 8. Return: SUCCESS (spec ready for planning) | |
| 26 | - | ``` | |
| 27 | - | ||
| 28 | - | --- | |
| 29 | - | ||
| 30 | - | ## ⚡ Quick Guidelines | |
| 31 | - | - ✅ Focus on WHAT users need and WHY | |
| 32 | - | - ❌ Avoid HOW to implement (no tech stack, APIs, code structure) | |
| 33 | - | - 👥 Written for business stakeholders, not developers | |
| 34 | - | ||
| 35 | - | ### Section Requirements | |
| 36 | - | - **Mandatory sections**: Must be completed for every feature | |
| 37 | - | - **Optional sections**: Include only when relevant to the feature | |
| 38 | - | - When a section doesn't apply, remove it entirely (don't leave as "N/A") | |
| 39 | - | ||
| 40 | - | ### For AI Generation | |
| 41 | - | When creating this spec from a user prompt: | |
| 42 | - | 1. **Mark all ambiguities**: Use [NEEDS CLARIFICATION: specific question] for any assumption you'd need to make | |
| 43 | - | 2. **Don't guess**: If the prompt doesn't specify something (e.g., "login system" without auth method), mark it | |
| 44 | - | 3. **Think like a tester**: Every vague requirement should fail the "testable and unambiguous" checklist item | |
| 45 | - | 4. **Common underspecified areas**: | |
| 46 | - | - User types and permissions | |
| 47 | - | - Data retention/deletion policies | |
| 48 | - | - Performance targets and scale | |
| 49 | - | - Error handling behaviors | |
| 50 | - | - Integration requirements | |
| 51 | - | - Security/compliance needs | |
| 52 | - | ||
| 53 | - | --- | |
| 54 | - | ||
| 55 | - | ## User Scenarios & Testing *(mandatory)* | |
| 56 | - | ||
| 57 | - | ### Primary User Story | |
| 58 | - | As a developer/power user of the dumb browser application, I need the browser to have full control over its web rendering engine and browser capabilities without being limited by third-party frameworks, so that I can customize browser behavior, optimize performance, and maintain direct access to all native browser features. | |
| 59 | - | ||
| 60 | - | ### Acceptance Scenarios | |
| 61 | - | 1. **Given** the current browser uses a third-party framework, **When** I replace it with a native solution, **Then** the browser maintains all existing functionality (navigation, zoom, keyboard controls, history) | |
| 62 | - | 2. **Given** the native browser backend is implemented, **When** I want to add custom browser features, **Then** I can directly access and modify browser engine capabilities without framework limitations | |
| 63 | - | 3. **Given** the browser is running with the native backend, **When** users interact with web pages, **Then** performance is equal to or better than the previous framework-based implementation | |
| 64 | - | 4. **Given** the native backend is active, **When** the browser encounters different web content types, **Then** all standard web technologies render correctly | |
| 65 | - | ||
| 66 | - | ### Edge Cases | |
| 67 | - | - What happens when the native bindings fail to load or initialize? | |
| 68 | - | - How does the system handle web pages that stress-test browser engine capabilities? | |
| 69 | - | - What occurs if the browser needs to interface with system-level features not exposed by the native bindings? | |
| 70 | - | ||
| 71 | - | ## Requirements *(mandatory)* | |
| 72 | - | ||
| 73 | - | ### Functional Requirements | |
| 74 | - | - **FR-001**: System MUST render web pages with full HTML5, CSS3, and JavaScript support equivalent to modern browsers | |
| 75 | - | - **FR-002**: System MUST maintain all existing browser controls (navigation, zoom, keyboard shortcuts) without regression | |
| 76 | - | - **FR-003**: System MUST preserve existing user data (history, bookmarks, zoom settings) during migration | |
| 77 | - | - **FR-004**: System MUST support the same web content types and media formats as the current implementation | |
| 78 | - | - **FR-005**: System MUST provide identical or improved page loading performance compared to current framework | |
| 79 | - | - **FR-006**: System MUST maintain cross-platform compatibility [NEEDS CLARIFICATION: which platforms need to be supported - Linux only, or multiple platforms?] | |
| 80 | - | - **FR-007**: System MUST handle browser crashes gracefully without data loss | |
| 81 | - | - **FR-008**: System MUST support developer tools and debugging capabilities for web content | |
| 82 | - | - **FR-009**: System MUST maintain security features like sandboxing and content security policies | |
| 83 | - | - **FR-010**: System MUST provide memory management equivalent to or better than current implementation | |
| 84 | - | ||
| 85 | - | ### Key Entities | |
| 86 | - | - **Browser Engine Interface**: The abstraction layer that handles web content rendering, JavaScript execution, and browser feature access | |
| 87 | - | - **Native Bindings**: The interface components that connect high-level application code with low-level browser engine capabilities | |
| 88 | - | - **Migration State**: Configuration and data preservation mechanisms that ensure seamless transition from old to new backend | |
| 89 | - | ||
| 90 | - | --- | |
| 91 | - | ||
| 92 | - | ## Review & Acceptance Checklist | |
| 93 | - | *GATE: Automated checks run during main() execution* | |
| 94 | - | ||
| 95 | - | ### Content Quality | |
| 96 | - | - [ ] No implementation details (languages, frameworks, APIs) | |
| 97 | - | - [ ] Focused on user value and business needs | |
| 98 | - | - [ ] Written for non-technical stakeholders | |
| 99 | - | - [ ] All mandatory sections completed | |
| 100 | - | ||
| 101 | - | ### Requirement Completeness | |
| 102 | - | - [ ] No [NEEDS CLARIFICATION] markers remain | |
| 103 | - | - [ ] Requirements are testable and unambiguous | |
| 104 | - | - [ ] Success criteria are measurable | |
| 105 | - | - [ ] Scope is clearly bounded | |
| 106 | - | - [ ] Dependencies and assumptions identified | |
| 107 | - | ||
| 108 | - | --- | |
| 109 | - | ||
| 110 | - | ## Execution Status | |
| 111 | - | *Updated by main() during processing* | |
| 112 | - | ||
| 113 | - | - [x] User description parsed | |
| 114 | - | - [x] Key concepts extracted | |
| 115 | - | - [x] Ambiguities marked | |
| 116 | - | - [x] User scenarios defined | |
| 117 | - | - [x] Requirements generated | |
| 118 | - | - [x] Entities identified | |
| 119 | - | - [ ] Review checklist passed | |
| 120 | - | ||
| 121 | - | ---⏎̸ | |
D specs/003-webkit2gtk-migration/tasks.md +0 -146
| @@ -1,146 +0,0 @@ | |||
| 1 | - | # Tasks: WebKit2GTK Native Browser Migration | |
| 2 | - | ||
| 3 | - | **Input**: Design documents from `/specs/003-webkit2gtk-migration/` | |
| 4 | - | **Prerequisites**: plan.md (✓), research.md (✓), data-model.md (✓), contracts/ (✓), quickstart.md (✓) | |
| 5 | - | ||
| 6 | - | ## Phase 3.1: Setup | |
| 7 | - | ||
| 8 | - | - [ ] T001 Clone WebKit2GTK reference repository to /home/brice/dev/clone/webkit2gtk-reference | |
| 9 | - | - [ ] T002 Install WebKit2GTK and GTK3 development dependencies on system | |
| 10 | - | - [x] T003 [P] Create pkg/webkit package structure with basic Go files | |
| 11 | - | - [x] T004 [P] Configure CGO build flags for WebKit2GTK and GTK3 in pkg/webkit | |
| 12 | - | - [x] T005 [P] Setup linting and formatting tools for CGO code | |
| 13 | - | ||
| 14 | - | ## Phase 3.2: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.3 | |
| 15 | - | ||
| 16 | - | **CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation** | |
| 17 | - | ||
| 18 | - | - [x] T006 [P] Contract test NewWebView function in tests/contract/test_webview_creation.go | |
| 19 | - | - [x] T007 [P] Contract test LoadURL navigation in tests/contract/test_navigation.go | |
| 20 | - | - [x] T008 [P] Contract test RegisterKeyboardShortcut in tests/contract/test_keyboard_shortcuts.go | |
| 21 | - | - [x] T009 [P] Contract test InjectScript functionality in tests/contract/test_script_injection.go | |
| 22 | - | - [x] T010 [P] Contract test SetZoom/GetZoom operations in tests/contract/test_zoom_control.go | |
| 23 | - | - [x] T011 [P] Contract test Show/Hide/Destroy lifecycle in tests/contract/test_lifecycle.go | |
| 24 | - | - [x] T012 [P] Integration test basic WebKit browser window in tests/integration/test_webkit_basic.go | |
| 25 | - | - [x] T013 [P] Integration test google.fr navigation in tests/integration/test_google_navigation.go | |
| 26 | - | - [x] T014 [P] Integration test keyboard shortcuts on external sites in tests/integration/test_external_shortcuts.go | |
| 27 | - | - [x] T015 [P] Integration test zoom persistence with database in tests/integration/test_zoom_persistence.go | |
| 28 | - | ||
| 29 | - | ## Phase 3.3: Core Implementation (ONLY after tests are failing) | |
| 30 | - | ||
| 31 | - | - [x] T016 [P] WebView struct and basic CGO wrapper in pkg/webkit/webview.go | |
| 32 | - | - [x] T017 [P] GTK Application window management in pkg/webkit/window.go | |
| 33 | - | - [x] T018 [P] WebKit settings configuration in pkg/webkit/settings.go | |
| 34 | - | - [x] T019 [P] Keyboard event handling with GTK in pkg/webkit/keyboard.go | |
| 35 | - | - [x] T020 [P] JavaScript injection via UserContentManager in pkg/webkit/script.go | |
| 36 | - | - [x] T021 [P] Zoom control WebKit API wrapper in pkg/webkit/zoom.go | |
| 37 | - | - [x] T022 NewWebView constructor function | |
| 38 | - | - [x] T023 LoadURL navigation implementation | |
| 39 | - | - [x] T024 RegisterKeyboardShortcut GTK event binding | |
| 40 | - | - [x] T025 InjectScript WebKit UserContentManager integration | |
| 41 | - | - [x] T026 SetZoom/GetZoom WebKit API calls | |
| 42 | - | - [x] T027 Show/Hide/Destroy lifecycle management | |
| 43 | - | - [x] T028 CGO memory management and finalizers | |
| 44 | - | - [ ] T029 Error handling and C to Go error propagation | |
| 45 | - | ||
| 46 | - | ## Phase 3.4: Integration | |
| 47 | - | ||
| 48 | - | - [x] T030 WebKit browser service integration in services/browser_service.go | |
| 49 | - | - [x] T031 Replace Wails ExecJS with WebKit InjectScript in services/browser_service.go | |
| 50 | - | - [x] T032 Integrate WebKit zoom with existing database storage in services/browser_service.go | |
| 51 | - | - [x] T033 Update main.go to use WebKit browser instead of Wails | |
| 52 | - | - [x] T034 Remove Wails periodic script injection, use WebKit UserContentManager | |
| 53 | - | - [x] T035 Update CLI commands to work with WebKit backend | |
| 54 | - | - [x] T036 Preserve existing keyboard shortcut behavior through GTK events | |
| 55 | - | ||
| 56 | - | ## Phase 3.5: Migration & Polish | |
| 57 | - | ||
| 58 | - | - [ ] T037 [P] Performance tests: startup time <500ms in tests/unit/test_performance.go | |
| 59 | - | - [ ] T038 [P] Performance tests: memory usage <100MB baseline in tests/unit/test_memory.go | |
| 60 | - | - [ ] T039 [P] Unit tests for WebKit error handling in tests/unit/test_error_handling.go | |
| 61 | - | - [ ] T040 [P] Unit tests for CGO memory management in tests/unit/test_memory_management.go | |
| 62 | - | - [x] T041 Data preservation validation: existing history and zoom settings | |
| 63 | - | - [x] T042 Remove Wails dependencies from go.mod and go.sum | |
| 64 | - | - [ ] T043 Remove frontend TypeScript build system (frontend/ directory) | |
| 65 | - | - [ ] T044 Remove Wails references from documentation and README | |
| 66 | - | - [ ] T045 [P] Update pkg/webkit documentation in llms.txt format | |
| 67 | - | - [ ] T046 Run quickstart.md validation scenarios | |
| 68 | - | - [ ] T047 Performance comparison: WebKit vs Wails baseline metrics | |
| 69 | - | ||
| 70 | - | ## Dependencies | |
| 71 | - | ||
| 72 | - | - Setup (T001-T005) before tests (T006-T015) | |
| 73 | - | - Tests (T006-T015) before implementation (T016-T029) | |
| 74 | - | - T016 blocks T022, T030, T033 | |
| 75 | - | - T017 blocks T027, T033 | |
| 76 | - | - T018 blocks T022, T026 | |
| 77 | - | - T019 blocks T024, T036 | |
| 78 | - | - T020 blocks T025, T031 | |
| 79 | - | - T021 blocks T026, T032 | |
| 80 | - | - Core implementation (T016-T029) before integration (T030-T036) | |
| 81 | - | - Integration (T030-T036) before migration (T042-T044) | |
| 82 | - | - Implementation before polish (T037-T047) | |
| 83 | - | ||
| 84 | - | ## Parallel Example | |
| 85 | - | ||
| 86 | - | ``` | |
| 87 | - | # Launch T006-T011 together (contract tests): | |
| 88 | - | Task: "Contract test NewWebView function in tests/contract/test_webview_creation.go" | |
| 89 | - | Task: "Contract test LoadURL navigation in tests/contract/test_navigation.go" | |
| 90 | - | Task: "Contract test RegisterKeyboardShortcut in tests/contract/test_keyboard_shortcuts.go" | |
| 91 | - | Task: "Contract test InjectScript functionality in tests/contract/test_script_injection.go" | |
| 92 | - | Task: "Contract test SetZoom/GetZoom operations in tests/contract/test_zoom_control.go" | |
| 93 | - | Task: "Contract test Show/Hide/Destroy lifecycle in tests/contract/test_lifecycle.go" | |
| 94 | - | ||
| 95 | - | # Launch T016-T021 together (core CGO wrappers): | |
| 96 | - | Task: "WebView struct and basic CGO wrapper in pkg/webkit/webview.go" | |
| 97 | - | Task: "GTK Application window management in pkg/webkit/window.go" | |
| 98 | - | Task: "WebKit settings configuration in pkg/webkit/settings.go" | |
| 99 | - | Task: "Keyboard event handling with GTK in pkg/webkit/keyboard.go" | |
| 100 | - | Task: "JavaScript injection via UserContentManager in pkg/webkit/script.go" | |
| 101 | - | Task: "Zoom control WebKit API wrapper in pkg/webkit/zoom.go" | |
| 102 | - | ``` | |
| 103 | - | ||
| 104 | - | ## Notes | |
| 105 | - | ||
| 106 | - | - [P] tasks = different files, no dependencies | |
| 107 | - | - Verify all contract tests fail before implementing | |
| 108 | - | - Commit after each task completion | |
| 109 | - | - WebKit2GTK reference repository provides C API examples | |
| 110 | - | - CGO memory management critical for stability | |
| 111 | - | - Preserve all existing user data during migration | |
| 112 | - | ||
| 113 | - | ## Task Generation Rules | |
| 114 | - | ||
| 115 | - | *Applied during main() execution* | |
| 116 | - | ||
| 117 | - | 1. **From Contracts**: | |
| 118 | - | - Each Go function in webkit-bindings-api.yaml → contract test task [P] | |
| 119 | - | - Each WebKit API operation → implementation task | |
| 120 | - | ||
| 121 | - | 2. **From Data Model**: | |
| 122 | - | - WebKit Browser Instance → WebView/Window/Settings tasks [P] | |
| 123 | - | - WebKit Bindings Interface → CGO wrapper tasks [P] | |
| 124 | - | - Migration State Manager → data preservation tasks | |
| 125 | - | ||
| 126 | - | 3. **From User Stories**: | |
| 127 | - | - google.fr navigation → integration test [P] | |
| 128 | - | - Keyboard shortcuts → integration test [P] | |
| 129 | - | - Zoom persistence → integration test [P] | |
| 130 | - | ||
| 131 | - | 4. **Ordering**: | |
| 132 | - | - Setup → Contract Tests → CGO Wrappers → API Functions → Integration → Migration → Polish | |
| 133 | - | - Dependencies block parallel execution | |
| 134 | - | ||
| 135 | - | ## Validation Checklist | |
| 136 | - | ||
| 137 | - | *GATE: Checked by main() before returning* | |
| 138 | - | ||
| 139 | - | - [x] All WebKit API contracts have corresponding tests | |
| 140 | - | - [x] All data model entities have implementation tasks | |
| 141 | - | - [x] All tests come before implementation (TDD enforced) | |
| 142 | - | - [x] Parallel tasks truly independent ([P] = different files) | |
| 143 | - | - [x] Each task specifies exact file path | |
| 144 | - | - [x] No task modifies same file as another [P] task | |
| 145 | - | - [x] Migration preserves user data (history, zoom settings) | |
| 146 | - | - [x] Performance requirements addressed (<500ms, <100MB) | |
D specs/004-migrate-to-webkitgtk/contracts/rendering-config.yaml +0 -153
| @@ -1,153 +0,0 @@ | |||
| 1 | - | # Rendering Configuration Contract | |
| 2 | - | # Defines the interface for GPU/CPU rendering configuration | |
| 3 | - | ||
| 4 | - | version: "1.0.0" | |
| 5 | - | component: "RenderingConfig" | |
| 6 | - | ||
| 7 | - | # Configuration Interface | |
| 8 | - | config: | |
| 9 | - | rendering_mode: | |
| 10 | - | type: "enum" | |
| 11 | - | values: | |
| 12 | - | - name: "auto" | |
| 13 | - | description: "Automatically detect GPU availability and use if present" | |
| 14 | - | default: true | |
| 15 | - | - name: "gpu" | |
| 16 | - | description: "Force GPU acceleration (fail if unavailable)" | |
| 17 | - | default: false | |
| 18 | - | - name: "cpu" | |
| 19 | - | description: "Force software rendering (disable GPU)" | |
| 20 | - | default: false | |
| 21 | - | ||
| 22 | - | settings: | |
| 23 | - | enable_2d_canvas: | |
| 24 | - | type: "boolean" | |
| 25 | - | default: true | |
| 26 | - | description: "Enable hardware acceleration for 2D canvas" | |
| 27 | - | ||
| 28 | - | enable_webgl: | |
| 29 | - | type: "boolean" | |
| 30 | - | default: true | |
| 31 | - | description: "Enable WebGL for 3D content" | |
| 32 | - | ||
| 33 | - | draw_compositing_indicators: | |
| 34 | - | type: "boolean" | |
| 35 | - | default: false | |
| 36 | - | description: "Show GPU compositing borders (debug)" | |
| 37 | - | ||
| 38 | - | # CLI Interface | |
| 39 | - | cli: | |
| 40 | - | flags: | |
| 41 | - | - name: "--rendering-mode" | |
| 42 | - | type: "string" | |
| 43 | - | values: ["auto", "gpu", "cpu"] | |
| 44 | - | default: "auto" | |
| 45 | - | description: "Set rendering mode" | |
| 46 | - | ||
| 47 | - | - name: "--disable-gpu" | |
| 48 | - | type: "boolean" | |
| 49 | - | default: false | |
| 50 | - | description: "Shorthand for --rendering-mode=cpu" | |
| 51 | - | ||
| 52 | - | - name: "--force-gpu" | |
| 53 | - | type: "boolean" | |
| 54 | - | default: false | |
| 55 | - | description: "Shorthand for --rendering-mode=gpu" | |
| 56 | - | ||
| 57 | - | - name: "--debug-gpu" | |
| 58 | - | type: "boolean" | |
| 59 | - | default: false | |
| 60 | - | description: "Enable GPU compositing indicators" | |
| 61 | - | ||
| 62 | - | # Environment Variables | |
| 63 | - | environment: | |
| 64 | - | - name: "DUMBER_RENDERING_MODE" | |
| 65 | - | values: ["auto", "gpu", "cpu"] | |
| 66 | - | description: "Override rendering mode" | |
| 67 | - | ||
| 68 | - | - name: "WEBKIT_DISABLE_COMPOSITING_MODE" | |
| 69 | - | values: ["1", "0"] | |
| 70 | - | description: "WebKit native disable flag" | |
| 71 | - | ||
| 72 | - | # Status API | |
| 73 | - | status: | |
| 74 | - | endpoint: "/api/rendering/status" | |
| 75 | - | response: | |
| 76 | - | mode: | |
| 77 | - | type: "string" | |
| 78 | - | enum: ["auto", "gpu", "cpu"] | |
| 79 | - | ||
| 80 | - | gpu_active: | |
| 81 | - | type: "boolean" | |
| 82 | - | description: "Whether GPU acceleration is currently active" | |
| 83 | - | ||
| 84 | - | gpu_available: | |
| 85 | - | type: "boolean" | |
| 86 | - | description: "Whether GPU hardware is available" | |
| 87 | - | ||
| 88 | - | vulkan_enabled: | |
| 89 | - | type: "boolean" | |
| 90 | - | description: "Whether Vulkan renderer is active" | |
| 91 | - | ||
| 92 | - | errors: | |
| 93 | - | type: "array" | |
| 94 | - | items: | |
| 95 | - | type: "object" | |
| 96 | - | properties: | |
| 97 | - | code: "string" | |
| 98 | - | message: "string" | |
| 99 | - | fallback_used: "boolean" | |
| 100 | - | ||
| 101 | - | performance: | |
| 102 | - | type: "object" | |
| 103 | - | properties: | |
| 104 | - | fps: "number" | |
| 105 | - | cpu_usage_percent: "number" | |
| 106 | - | gpu_usage_percent: "number" | |
| 107 | - | memory_mb: "integer" | |
| 108 | - | ||
| 109 | - | # Validation Rules | |
| 110 | - | validation: | |
| 111 | - | startup: | |
| 112 | - | - check: "GPU availability if mode=gpu" | |
| 113 | - | error: "GPU acceleration requested but not available" | |
| 114 | - | action: "fail_startup" | |
| 115 | - | ||
| 116 | - | - check: "Vulkan support if GPU active" | |
| 117 | - | warning: "Vulkan not available, using OpenGL" | |
| 118 | - | action: "log_warning" | |
| 119 | - | ||
| 120 | - | - check: "Driver compatibility" | |
| 121 | - | error: "GPU driver incompatible" | |
| 122 | - | action: "fallback_to_cpu" | |
| 123 | - | ||
| 124 | - | runtime: | |
| 125 | - | - check: "GPU memory < 500MB" | |
| 126 | - | warning: "High GPU memory usage" | |
| 127 | - | action: "log_metric" | |
| 128 | - | ||
| 129 | - | - check: "FPS > 30" | |
| 130 | - | warning: "Low frame rate detected" | |
| 131 | - | action: "log_metric" | |
| 132 | - | ||
| 133 | - | # Error Codes | |
| 134 | - | errors: | |
| 135 | - | GPU_NOT_AVAILABLE: | |
| 136 | - | code: "E001" | |
| 137 | - | message: "GPU hardware not detected" | |
| 138 | - | severity: "error" | |
| 139 | - | ||
| 140 | - | VULKAN_INIT_FAILED: | |
| 141 | - | code: "E002" | |
| 142 | - | message: "Failed to initialize Vulkan renderer" | |
| 143 | - | severity: "warning" | |
| 144 | - | ||
| 145 | - | DRIVER_INCOMPATIBLE: | |
| 146 | - | code: "E003" | |
| 147 | - | message: "GPU driver version incompatible" | |
| 148 | - | severity: "error" | |
| 149 | - | ||
| 150 | - | MEMORY_EXCEEDED: | |
| 151 | - | code: "W001" | |
| 152 | - | message: "GPU memory usage exceeded threshold" | |
| 153 | - | severity: "warning"⏎̸ | |
D specs/004-migrate-to-webkitgtk/contracts/webkit-api.yaml +0 -111
| @@ -1,111 +0,0 @@ | |||
| 1 | - | # WebKit API Migration Contract | |
| 2 | - | # Defines the interface mapping between WebKit2GTK 4.0 and WebKitGTK 6.0 | |
| 3 | - | ||
| 4 | - | version: "1.0.0" | |
| 5 | - | migration: | |
| 6 | - | from: "webkit2gtk-4.0" | |
| 7 | - | to: "webkitgtk-6.0" | |
| 8 | - | ||
| 9 | - | # Core WebView Management | |
| 10 | - | webview: | |
| 11 | - | creation: | |
| 12 | - | old: | |
| 13 | - | function: "webkit_web_view_new_with_context" | |
| 14 | - | params: ["WebKitWebContext*"] | |
| 15 | - | returns: "GtkWidget*" | |
| 16 | - | new: | |
| 17 | - | function: "g_object_new" | |
| 18 | - | params: ["WEBKIT_TYPE_WEB_VIEW", "properties..."] | |
| 19 | - | returns: "GtkWidget*" | |
| 20 | - | ||
| 21 | - | settings: | |
| 22 | - | hardware_acceleration: | |
| 23 | - | function: "webkit_settings_set_hardware_acceleration_policy" | |
| 24 | - | params: ["WebKitSettings*", "WebKitHardwareAccelerationPolicy"] | |
| 25 | - | values: | |
| 26 | - | - WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND | |
| 27 | - | - WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS | |
| 28 | - | - WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER | |
| 29 | - | ||
| 30 | - | canvas_acceleration: | |
| 31 | - | function: "webkit_settings_set_enable_2d_canvas_acceleration" | |
| 32 | - | params: ["WebKitSettings*", "gboolean"] | |
| 33 | - | ||
| 34 | - | webgl: | |
| 35 | - | function: "webkit_settings_set_enable_webgl" | |
| 36 | - | params: ["WebKitSettings*", "gboolean"] | |
| 37 | - | ||
| 38 | - | # GTK4 Widget Changes | |
| 39 | - | gtk: | |
| 40 | - | window: | |
| 41 | - | create: | |
| 42 | - | old: "gtk_window_new(GTK_WINDOW_TOPLEVEL)" | |
| 43 | - | new: "gtk_window_new()" | |
| 44 | - | ||
| 45 | - | add_child: | |
| 46 | - | old: "gtk_container_add(container, widget)" | |
| 47 | - | new: "gtk_window_set_child(window, widget)" | |
| 48 | - | ||
| 49 | - | destroy: | |
| 50 | - | old: "gtk_widget_destroy(widget)" | |
| 51 | - | new: "gtk_window_destroy(GTK_WINDOW(widget))" | |
| 52 | - | ||
| 53 | - | events: | |
| 54 | - | key_press: | |
| 55 | - | old: | |
| 56 | - | signal: "key-press-event" | |
| 57 | - | callback: "gboolean (*)(GtkWidget*, GdkEventKey*, gpointer)" | |
| 58 | - | new: | |
| 59 | - | controller: "gtk_event_controller_key_new()" | |
| 60 | - | signal: "key-pressed" | |
| 61 | - | callback: "gboolean (*)(GtkEventControllerKey*, guint, guint, GdkModifierType, gpointer)" | |
| 62 | - | ||
| 63 | - | button_press: | |
| 64 | - | old: | |
| 65 | - | signal: "button-press-event" | |
| 66 | - | callback: "gboolean (*)(GtkWidget*, GdkEventButton*, gpointer)" | |
| 67 | - | new: | |
| 68 | - | controller: "gtk_gesture_click_new()" | |
| 69 | - | signal: "pressed" | |
| 70 | - | callback: "void (*)(GtkGestureClick*, gint, gdouble, gdouble, gpointer)" | |
| 71 | - | ||
| 72 | - | # Network Session (replaces WebContext) | |
| 73 | - | network: | |
| 74 | - | session: | |
| 75 | - | old: | |
| 76 | - | type: "WebKitWebContext" | |
| 77 | - | data_manager: "webkit_website_data_manager_new" | |
| 78 | - | new: | |
| 79 | - | type: "WebKitNetworkSession" | |
| 80 | - | create: "webkit_network_session_new" | |
| 81 | - | ephemeral: "webkit_network_session_new_ephemeral" | |
| 82 | - | default: "webkit_network_session_get_default" | |
| 83 | - | ||
| 84 | - | # Build Configuration | |
| 85 | - | build: | |
| 86 | - | pkg_config: | |
| 87 | - | old: | |
| 88 | - | - "webkit2gtk-4.0" | |
| 89 | - | - "gtk+-3.0" | |
| 90 | - | - "javascriptcoregtk-4.0" | |
| 91 | - | new: | |
| 92 | - | - "webkitgtk-6.0" | |
| 93 | - | - "gtk4" | |
| 94 | - | - "javascriptcoregtk-6.0" | |
| 95 | - | ||
| 96 | - | headers: | |
| 97 | - | old: | |
| 98 | - | - "#include <webkit2/webkit2.h>" | |
| 99 | - | - "#include <gtk/gtk.h>" | |
| 100 | - | new: | |
| 101 | - | - "#include <webkit/webkit.h>" | |
| 102 | - | - "#include <gtk/gtk.h>" | |
| 103 | - | ||
| 104 | - | # Compatibility Requirements | |
| 105 | - | compatibility: | |
| 106 | - | minimum_gtk: "4.0" | |
| 107 | - | minimum_webkit: "2.40" # First version with webkitgtk-6.0 | |
| 108 | - | required_features: | |
| 109 | - | - hardware_acceleration_policy | |
| 110 | - | - network_session | |
| 111 | - | - sandbox_always_enabled⏎̸ | |
D specs/004-migrate-to-webkitgtk/data-model.md +0 -170
| @@ -1,170 +0,0 @@ | |||
| 1 | - | # Data Model: WebKitGTK 6.0 Migration | |
| 2 | - | ||
| 3 | - | ## Configuration Model | |
| 4 | - | ||
| 5 | - | ### RenderingConfig | |
| 6 | - | ```go | |
| 7 | - | type RenderingMode string | |
| 8 | - | ||
| 9 | - | const ( | |
| 10 | - | RenderingModeAuto RenderingMode = "auto" // Detect GPU availability | |
| 11 | - | RenderingModeGPU RenderingMode = "gpu" // Force GPU acceleration | |
| 12 | - | RenderingModeCPU RenderingMode = "cpu" // Force software rendering | |
| 13 | - | ) | |
| 14 | - | ||
| 15 | - | type RenderingConfig struct { | |
| 16 | - | Mode RenderingMode // Default: auto | |
| 17 | - | Enable2DCanvas bool // Default: true | |
| 18 | - | EnableWebGL bool // Default: true | |
| 19 | - | DrawCompositingIndicators bool // Default: false (debug only) | |
| 20 | - | } | |
| 21 | - | ``` | |
| 22 | - | ||
| 23 | - | ### Updated WebKit Config | |
| 24 | - | ```go | |
| 25 | - | type Config struct { | |
| 26 | - | // Existing fields | |
| 27 | - | InitialURL string | |
| 28 | - | UserAgent string | |
| 29 | - | EnableDeveloperExtras bool | |
| 30 | - | ZoomDefault float64 | |
| 31 | - | DataDir string | |
| 32 | - | CacheDir string | |
| 33 | - | DefaultSansFont string | |
| 34 | - | DefaultSerifFont string | |
| 35 | - | DefaultMonospaceFont string | |
| 36 | - | DefaultFontSize int | |
| 37 | - | ||
| 38 | - | // New GPU rendering fields | |
| 39 | - | Rendering RenderingConfig | |
| 40 | - | } | |
| 41 | - | ``` | |
| 42 | - | ||
| 43 | - | ## API Mapping Model | |
| 44 | - | ||
| 45 | - | ### Core WebView APIs | |
| 46 | - | | Component | WebKit2GTK 4.0 | WebKitGTK 6.0 | Status | | |
| 47 | - | |-----------|---------------|---------------|---------| | |
| 48 | - | | WebView Creation | `webkit_web_view_new_with_context()` | `g_object_new(WEBKIT_TYPE_WEB_VIEW, ...)` | Breaking | | |
| 49 | - | | Context | `WebKitWebContext` | `WebKitNetworkSession` | Breaking | | |
| 50 | - | | Settings | `WebKitSettings` | `WebKitSettings` (expanded) | Compatible | | |
| 51 | - | | UserContentManager | Same | Same | Compatible | | |
| 52 | - | | JavaScript | `webkit_web_view_run_javascript()` | Same (async only) | Compatible | | |
| 53 | - | ||
| 54 | - | ### GTK Widget APIs | |
| 55 | - | | Component | GTK3 | GTK4 | Status | | |
| 56 | - | |-----------|------|------|---------| | |
| 57 | - | | Window | `gtk_window_new(GTK_WINDOW_TOPLEVEL)` | `gtk_window_new()` | Breaking | | |
| 58 | - | | Container | `gtk_container_add()` | `gtk_window_set_child()` | Breaking | | |
| 59 | - | | Events | `GdkEventKey*` | `GtkEventController` | Breaking | | |
| 60 | - | | Show/Hide | `gtk_widget_show()` | Same | Compatible | | |
| 61 | - | | Destroy | `gtk_widget_destroy()` | `gtk_window_destroy()` | Breaking | | |
| 62 | - | ||
| 63 | - | ### Hardware Acceleration APIs | |
| 64 | - | ```go | |
| 65 | - | // New acceleration policy enum | |
| 66 | - | type HardwareAccelerationPolicy int | |
| 67 | - | ||
| 68 | - | const ( | |
| 69 | - | PolicyOnDemand HardwareAccelerationPolicy = iota // Auto-detect | |
| 70 | - | PolicyAlways // Force GPU | |
| 71 | - | PolicyNever // Force CPU | |
| 72 | - | ) | |
| 73 | - | ||
| 74 | - | // Mapping to WebKit constants | |
| 75 | - | var policyMap = map[RenderingMode]HardwareAccelerationPolicy{ | |
| 76 | - | RenderingModeAuto: PolicyOnDemand, | |
| 77 | - | RenderingModeGPU: PolicyAlways, | |
| 78 | - | RenderingModeCPU: PolicyNever, | |
| 79 | - | } | |
| 80 | - | ``` | |
| 81 | - | ||
| 82 | - | ## Migration States | |
| 83 | - | ||
| 84 | - | ### File Migration Status | |
| 85 | - | ```go | |
| 86 | - | type MigrationStatus string | |
| 87 | - | ||
| 88 | - | const ( | |
| 89 | - | StatusPending MigrationStatus = "pending" | |
| 90 | - | StatusInProgress MigrationStatus = "in_progress" | |
| 91 | - | StatusComplete MigrationStatus = "complete" | |
| 92 | - | StatusTested MigrationStatus = "tested" | |
| 93 | - | ) | |
| 94 | - | ||
| 95 | - | type FileMigration struct { | |
| 96 | - | Path string | |
| 97 | - | Status MigrationStatus | |
| 98 | - | Changes []string // List of API changes made | |
| 99 | - | Tests []string // Associated test files | |
| 100 | - | } | |
| 101 | - | ``` | |
| 102 | - | ||
| 103 | - | ## Error Handling Model | |
| 104 | - | ||
| 105 | - | ### GPU Fallback Errors | |
| 106 | - | ```go | |
| 107 | - | type GPUError struct { | |
| 108 | - | Type string // "initialization", "driver", "memory" | |
| 109 | - | Message string | |
| 110 | - | Fallback bool // Whether CPU fallback was successful | |
| 111 | - | } | |
| 112 | - | ||
| 113 | - | type RenderingStatus struct { | |
| 114 | - | Mode RenderingMode | |
| 115 | - | GPUActive bool | |
| 116 | - | Errors []GPUError | |
| 117 | - | Performance struct { | |
| 118 | - | FPS float64 | |
| 119 | - | CPUUsage float64 | |
| 120 | - | GPUUsage float64 | |
| 121 | - | MemoryMB int | |
| 122 | - | } | |
| 123 | - | } | |
| 124 | - | ``` | |
| 125 | - | ||
| 126 | - | ## Build Configuration | |
| 127 | - | ||
| 128 | - | ### Package Config Changes | |
| 129 | - | ```makefile | |
| 130 | - | # Old build flags | |
| 131 | - | WEBKIT_PKG = webkit2gtk-4.0 | |
| 132 | - | GTK_PKG = gtk+-3.0 | |
| 133 | - | JS_PKG = javascriptcoregtk-4.0 | |
| 134 | - | ||
| 135 | - | # New build flags | |
| 136 | - | WEBKIT_PKG = webkitgtk-6.0 | |
| 137 | - | GTK_PKG = gtk4 | |
| 138 | - | JS_PKG = javascriptcoregtk-6.0 | |
| 139 | - | ``` | |
| 140 | - | ||
| 141 | - | ## Validation Rules | |
| 142 | - | ||
| 143 | - | ### Rendering Mode Validation | |
| 144 | - | - If GPU forced but unavailable → Error with suggestion to use auto | |
| 145 | - | - If CPU forced → Warn about performance impact | |
| 146 | - | - If auto → Log detected mode at startup | |
| 147 | - | ||
| 148 | - | ### Performance Thresholds | |
| 149 | - | - Startup time must remain < 500ms | |
| 150 | - | - GPU memory usage < 500MB | |
| 151 | - | - CPU usage reduction > 20% when GPU active | |
| 152 | - | - FPS improvement > 30% for animations | |
| 153 | - | ||
| 154 | - | ## State Transitions | |
| 155 | - | ||
| 156 | - | ### Rendering Mode State Machine | |
| 157 | - | ``` | |
| 158 | - | ┌─────┐ Check GPU ┌──────┐ Success ┌─────┐ | |
| 159 | - | │Auto │────────────→│Detect│────────→│GPU │ | |
| 160 | - | └─────┘ └──────┘ └─────┘ | |
| 161 | - | │ Fail │ Error | |
| 162 | - | ↓ ↓ | |
| 163 | - | ┌─────┐ ┌─────┐ | |
| 164 | - | │CPU │←─────────│Retry│ | |
| 165 | - | └─────┘ Fallback └─────┘ | |
| 166 | - | ``` | |
| 167 | - | ||
| 168 | - | ## Data Persistence | |
| 169 | - | ||
| 170 | - | No changes to existing SQLite schema required. Rendering mode stored in config file only.⏎̸ | |
D specs/004-migrate-to-webkitgtk/plan.md +0 -251
| @@ -1,251 +0,0 @@ | |||
| 1 | - | # Implementation Plan: Migrate to WebKitGTK 6.0 | |
| 2 | - | ||
| 3 | - | **Branch**: `004-migrate-to-webkitgtk` | **Date**: 2025-01-21 | **Spec**: [spec.md](./spec.md) | |
| 4 | - | **Input**: Feature specification from `/specs/004-migrate-to-webkitgtk/spec.md` | |
| 5 | - | ||
| 6 | - | ## Execution Flow (/plan command scope) | |
| 7 | - | ``` | |
| 8 | - | 1. Load feature spec from Input path | |
| 9 | - | → Successfully loaded spec for WebKitGTK 6.0 migration | |
| 10 | - | 2. Fill Technical Context (scan for NEEDS CLARIFICATION) | |
| 11 | - | → Project Type: Single (Go browser application) | |
| 12 | - | → Structure Decision: Option 1 (single project) | |
| 13 | - | → Open clarifications remain in spec (FR-008, FR-011, FR-012) | |
| 14 | - | 3. Evaluate Constitution Check section below | |
| 15 | - | → Adjust for remaining clarifications; document deviations | |
| 16 | - | → Update Progress Tracking: Initial Constitution Check | |
| 17 | - | 4. Execute Phase 0 → research.md (complete) | |
| 18 | - | → Research WebKit API differences and migration path | |
| 19 | - | 5. Execute Phase 1 → contracts, data-model.md, quickstart.md (complete) | |
| 20 | - | 6. Re-evaluate Constitution Check section | |
| 21 | - | → Design aligned with constitution principles; clarifications still pending | |
| 22 | - | → Update Progress Tracking: Post-Design Constitution Check | |
| 23 | - | 7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) (complete) | |
| 24 | - | 8. Generate tasks via /tasks (exists: tasks.md) | |
| 25 | - | 9. Track Phase 4 implementation progress (in progress) | |
| 26 | - | ``` | |
| 27 | - | ||
| 28 | - | ## Summary | |
| 29 | - | Migrate the dumber browser from WebKit2GTK 4.0 (GTK3) to WebKitGTK 6.0 (GTK4) to enable GPU rendering through Vulkan layer. The migration will involve incrementally updating the pkg/webkit package files while maintaining browser functionality. A global rendering configuration will be added to allow users to choose between CPU and GPU rendering, with GPU enabled by default when supported. | |
| 30 | - | ||
| 31 | - | ## Technical Context | |
| 32 | - | **Language/Version**: Go 1.25.1 | |
| 33 | - | **Primary Dependencies**: WebKitGTK 6.0, GTK4, libsoup3, SQLite3 | |
| 34 | - | **Storage**: SQLite3 for history/settings, WebKitWebsiteDataManager for browser data | |
| 35 | - | **Testing**: Go tests, contract tests for WebKit bindings | |
| 36 | - | **Target Platform**: Linux (Wayland-first, X11 compatible) | |
| 37 | - | **Project Type**: single - Go browser application | |
| 38 | - | **Performance Goals**: < 500ms startup, improved GPU rendering performance | |
| 39 | - | **Constraints**: Maintain all existing functionality, graceful fallback for non-Vulkan systems | |
| 40 | - | **Scale/Scope**: ~15 files in pkg/webkit to migrate, ~3000 LOC | |
| 41 | - | ||
| 42 | - | **User-Provided Context**: No TDD for this, we will start by checking the WebKit API differences and migrate pkg/webkit files one by one | |
| 43 | - | ||
| 44 | - | ## Current Snapshot (repo state) | |
| 45 | - | - Build flags already target GTK4/WebKitGTK 6.0 in `pkg/webkit/*_cgo.go` ✓ | |
| 46 | - | - Core files present: `webview_cgo.go`, `window_cgo.go`, `script_cgo.go`, `scheme_cgo.go`, `zoom_cgo.go`, `keyboard_cgo.go`, `devtools_cgo.go`, `loop_cgo.go`, plus Go wrappers (`*.go`) ✓ | |
| 47 | - | - Migration underway in `webview_cgo.go` (GTK4 APIs, evaluate_javascript) ✓ | |
| 48 | - | - Spec still has [NEEDS CLARIFICATION] for performance targets and timeline ✗ | |
| 49 | - | ||
| 50 | - | ## Constitution Check | |
| 51 | - | *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | |
| 52 | - | ||
| 53 | - | **Simplicity**: | |
| 54 | - | - Projects: 1 (single Go browser project) ✓ | |
| 55 | - | - Using framework directly? YES (direct CGO bindings to WebKitGTK) ✓ | |
| 56 | - | - Single data model? YES (existing models unchanged) ✓ | |
| 57 | - | - Avoiding patterns? YES (no unnecessary abstractions) ✓ | |
| 58 | - | ||
| 59 | - | **Architecture**: | |
| 60 | - | - EVERY feature as library? pkg/webkit is already a library ✓ | |
| 61 | - | - Libraries listed: pkg/webkit (WebKit2GTK Go bindings) | |
| 62 | - | - CLI per library: Browser CLI with browse, history, dmenu commands ✓ | |
| 63 | - | - Library docs: Will update with new API documentation | |
| 64 | - | ||
| 65 | - | **Testing (Modified per user request)**: | |
| 66 | - | - User specified: "No TDD for this" - migration-focused approach | |
| 67 | - | - Will add tests after migration for regression prevention | |
| 68 | - | - Contract tests for new WebKit bindings | |
| 69 | - | - Integration tests for browser functionality | |
| 70 | - | ||
| 71 | - | **Observability**: | |
| 72 | - | - Structured logging included? YES (slog) ✓ | |
| 73 | - | - Frontend logs → backend? N/A (native application) | |
| 74 | - | - Error context sufficient? YES ✓ | |
| 75 | - | ||
| 76 | - | **Versioning**: | |
| 77 | - | - Version number assigned? Will increment after migration | |
| 78 | - | - BUILD increments on every change? YES ✓ | |
| 79 | - | - Breaking changes handled? API compatibility layer during migration | |
| 80 | - | ||
| 81 | - | ## Project Structure | |
| 82 | - | ||
| 83 | - | ### Documentation (this feature) | |
| 84 | - | ``` | |
| 85 | - | specs/004-migrate-to-webkitgtk/ | |
| 86 | - | ├── plan.md # This file (/plan command output) | |
| 87 | - | ├── research.md # Phase 0 output (/plan command) | |
| 88 | - | ├── data-model.md # Phase 1 output (/plan command) | |
| 89 | - | ├── quickstart.md # Phase 1 output (/plan command) | |
| 90 | - | ├── contracts/ # Phase 1 output (/plan command) | |
| 91 | - | └── tasks.md # Phase 2 output (/tasks command - NOT created by /plan) | |
| 92 | - | ``` | |
| 93 | - | ||
| 94 | - | ### Source Code (repository root) | |
| 95 | - | ``` | |
| 96 | - | # Option 1: Single project (SELECTED) | |
| 97 | - | pkg/ | |
| 98 | - | └── webkit/ # WebKitGTK Go bindings (migration target) | |
| 99 | - | ├── webview_cgo.go # WebView implementation (GTK4/WebKit 6) | |
| 100 | - | ├── window_cgo.go # Window management (GTK4) | |
| 101 | - | ├── script_cgo.go # JavaScript evaluation/injection | |
| 102 | - | ├── scheme_cgo.go # Custom URI scheme handler | |
| 103 | - | ├── zoom_cgo.go # Zoom control | |
| 104 | - | ├── keyboard_cgo.go # Keyboard handling (controllers) | |
| 105 | - | ├── devtools_cgo.go # Inspector | |
| 106 | - | ├── loop_cgo.go # Main loop helpers | |
| 107 | - | ├── settings.go # High-level settings glue | |
| 108 | - | └── *.go # Non-CGO wrappers (window.go, zoom.go, script.go, ...) | |
| 109 | - | ||
| 110 | - | internal/ | |
| 111 | - | ├── cli/ # CLI entry points (browse, history, dmenu) | |
| 112 | - | ├── config/ # App config (extend for rendering) | |
| 113 | - | └── db/ # SQLite persistence | |
| 114 | - | ||
| 115 | - | tests/ | |
| 116 | - | ├── contract/ # Contract tests for WebKit bindings | |
| 117 | - | ├── integration/ # End-to-end validation | |
| 118 | - | └── unit/ # Unit tests | |
| 119 | - | ``` | |
| 120 | - | ||
| 121 | - | **Structure Decision**: Option 1 (Single project) - maintaining existing structure | |
| 122 | - | ||
| 123 | - | ## Phase 0: Outline & Research | |
| 124 | - | 1. **Extract unknowns from Technical Context**: | |
| 125 | - | - WebKitGTK 6.0 API changes from 4.0 | |
| 126 | - | - GTK4 migration requirements | |
| 127 | - | - Vulkan renderer configuration | |
| 128 | - | - CGO binding updates needed | |
| 129 | - | - Build system changes (pkg-config) | |
| 130 | - | ||
| 131 | - | 2. **Generate and dispatch research agents**: | |
| 132 | - | ``` | |
| 133 | - | Task: "Research WebKitGTK 6.0 API breaking changes" | |
| 134 | - | Task: "Find GTK3 to GTK4 migration patterns for CGO" | |
| 135 | - | Task: "Research Vulkan enablement in WebKitGTK 6.0" | |
| 136 | - | Task: "Identify deprecated WebKit2GTK 4.0 APIs" | |
| 137 | - | ``` | |
| 138 | - | ||
| 139 | - | 3. **Consolidate findings** in `research.md` | |
| 140 | - | ||
| 141 | - | **Output**: research.md with migration path defined | |
| 142 | - | ||
| 143 | - | ## Phase 1: Design & Contracts | |
| 144 | - | *Prerequisites: research.md complete* | |
| 145 | - | ||
| 146 | - | 1. **API Mapping** → `data-model.md`: | |
| 147 | - | - Map WebKit2GTK 4.0 APIs to WebKitGTK 6.0 equivalents | |
| 148 | - | - Document removed/replaced functions | |
| 149 | - | - Identify new required APIs | |
| 150 | - | ||
| 151 | - | 2. **Generate migration contracts**: | |
| 152 | - | - Define compatibility layer interfaces | |
| 153 | - | - Create migration checkpoints | |
| 154 | - | - Output to `/contracts/` | |
| 155 | - | ||
| 156 | - | 3. **Migration test scenarios**: | |
| 157 | - | - Test each webkit file migration | |
| 158 | - | - Verify GPU acceleration | |
| 159 | - | - Fallback testing | |
| 160 | - | ||
| 161 | - | 4. **Create quickstart guide**: | |
| 162 | - | - Build requirements for GTK4/WebKitGTK 6.0 | |
| 163 | - | - Verification steps | |
| 164 | - | - Performance testing | |
| 165 | - | ||
| 166 | - | 5. **Update CLAUDE.md**: | |
| 167 | - | - Add WebKitGTK 6.0 context | |
| 168 | - | - GTK4 migration notes | |
| 169 | - | - Recent changes | |
| 170 | - | ||
| 171 | - | **Output**: data-model.md, /contracts/*, quickstart.md, CLAUDE.md updates | |
| 172 | - | ||
| 173 | - | ## File‑By‑File Migration Plan (grounded in repo) | |
| 174 | - | - `pkg/webkit/build_flags_cgo.go` / `build_cgo_stub.go` / `build_flags_stub.go`: ensure pkg-config switched to `webkitgtk-6.0 gtk4 javascriptcoregtk-6.0` (present; verify includes and tags) | |
| 175 | - | - `pkg/webkit/webview_cgo.go`: use `g_object_new` patterns as needed; ensure `webkit_web_view_evaluate_javascript` (async) usage; connect notify signals via GTK4; migrate any deprecated UCM message handlers. | |
| 176 | - | - `pkg/webkit/window_cgo.go`: use `gtk_window_new()`, `gtk_window_set_child()`, and `gtk_window_destroy()`; remove `gtk_container_add()` remnants. | |
| 177 | - | - `pkg/webkit/keyboard_cgo.go`: replace GdkEvent handlers with `GtkEventControllerKey` (key-pressed) and gestures for mouse input. | |
| 178 | - | - `pkg/webkit/zoom_cgo.go` / `zoom.go`: confirm zoom ranges and GTK4 APIs for zoom if used; keep high-level validation in Go. | |
| 179 | - | - `pkg/webkit/script_cgo.go` / `script.go`: standardize JS evaluation via `webkit_web_view_evaluate_javascript`. | |
| 180 | - | - `pkg/webkit/scheme_cgo.go`: verify `WebKitURISchemeRequest` handling and memory ownership semantics on GTK4/WebKit 6. | |
| 181 | - | - `pkg/webkit/devtools_cgo.go`: validate inspector APIs on WebKit 6. | |
| 182 | - | - `pkg/webkit/loop_cgo.go`: update any deprecated main-loop helpers. | |
| 183 | - | - `internal/config/*`: add `RenderingConfig` and `RenderingMode` with env/flag wiring. | |
| 184 | - | - `internal/cli/browse.go`: add `--rendering-mode`, `--disable-gpu`, `--debug-gpu`. | |
| 185 | - | - `services/*`: plumb rendering config into WebView creation. | |
| 186 | - | ||
| 187 | - | ## Phase 2: Task Planning Approach | |
| 188 | - | *This section describes what the /tasks command will do - DO NOT execute during /plan* | |
| 189 | - | ||
| 190 | - | **Task Generation Strategy**: | |
| 191 | - | - Analyze each file in pkg/webkit for required changes | |
| 192 | - | - Create migration task for each file | |
| 193 | - | - Order by dependency (build files first, then core, then features) | |
| 194 | - | - Add verification tasks after each major component | |
| 195 | - | ||
| 196 | - | **Ordering Strategy**: | |
| 197 | - | 1. Build configuration (pkg-config, CGO flags) | |
| 198 | - | 2. Core types and structures | |
| 199 | - | 3. Window and WebView creation | |
| 200 | - | 4. Feature-specific files (zoom, script, keyboard) | |
| 201 | - | 5. Integration testing | |
| 202 | - | 6. Performance verification | |
| 203 | - | ||
| 204 | - | **Estimated Output**: 20-25 migration tasks in tasks.md | |
| 205 | - | ||
| 206 | - | **IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan | |
| 207 | - | ||
| 208 | - | ## Phase 3+: Future Implementation | |
| 209 | - | *These phases are beyond the scope of the /plan command* | |
| 210 | - | ||
| 211 | - | **Phase 3**: Task execution (/tasks command creates tasks.md) | |
| 212 | - | **Phase 4**: Implementation (execute migration tasks) | |
| 213 | - | **Phase 5**: Validation (verify GPU acceleration, run performance tests) | |
| 214 | - | ||
| 215 | - | ## Risks & Mitigations | |
| 216 | - | - Driver variability: prefer ON_DEMAND policy by default; expose override flags; add CPU fallback on init failures. | |
| 217 | - | - API drift: adhere to contracts in `contracts/webkit-api.yaml`; gate changes behind compile tags where helpful. | |
| 218 | - | - Performance regressions: provide quickstart validation and capture metrics; keep rollback point per task. | |
| 219 | - | ||
| 220 | - | ## Complexity Tracking | |
| 221 | - | *Fill ONLY if Constitution Check has violations that must be justified* | |
| 222 | - | ||
| 223 | - | | Violation | Why Needed | Simpler Alternative Rejected Because | | |
| 224 | - | |-----------|------------|-------------------------------------| | |
| 225 | - | | No TDD for migration | User-specified approach | TDD would slow down API exploration during migration | | |
| 226 | - | ||
| 227 | - | ## Progress Tracking | |
| 228 | - | *This checklist is updated during execution flow* | |
| 229 | - | ||
| 230 | - | **Phase Status**: | |
| 231 | - | - [x] Phase 0: Research complete (/plan command) | |
| 232 | - | - [x] Phase 1: Design complete (/plan command) | |
| 233 | - | - [x] Phase 2: Task planning complete (/plan command - describe approach only) | |
| 234 | - | - [x] Phase 3: Tasks generated (/tasks command) | |
| 235 | - | - [ ] Phase 4: Implementation in progress | |
| 236 | - | - [ ] Phase 5: Validation passed | |
| 237 | - | ||
| 238 | - | **Gate Status**: | |
| 239 | - | - [x] Initial Constitution Check: PASS | |
| 240 | - | - [x] Post-Design Constitution Check: PASS (performance targets pending) | |
| 241 | - | - [ ] All NEEDS CLARIFICATION resolved (see spec FR-008, FR-011, FR-012) | |
| 242 | - | - [x] Complexity deviations documented | |
| 243 | - | ||
| 244 | - | ## Next Actions | |
| 245 | - | - Verify and finalize build flags and includes across `pkg/webkit/*_cgo.go`. | |
| 246 | - | - Align `internal/config` and `internal/cli` with `RenderingConfig` and flags. | |
| 247 | - | - Complete event/gesture migration in `keyboard_cgo.go` and related handlers. | |
| 248 | - | - Add hardware acceleration policy mapping during WebView initialization. | |
| 249 | - | ||
| 250 | - | --- | |
| 251 | - | *Based on Constitution v1.0.0 - See `/memory/constitution.md`* | |
D specs/004-migrate-to-webkitgtk/quickstart.md +0 -194
| @@ -1,194 +0,0 @@ | |||
| 1 | - | # Quickstart: WebKitGTK 6.0 Migration | |
| 2 | - | ||
| 3 | - | ## Prerequisites | |
| 4 | - | ||
| 5 | - | ### System Requirements | |
| 6 | - | ```bash | |
| 7 | - | # Check GTK4 installation | |
| 8 | - | pkg-config --modversion gtk4 # Should be >= 4.0 | |
| 9 | - | ||
| 10 | - | # Check WebKitGTK 6.0 | |
| 11 | - | pkg-config --modversion webkitgtk-6.0 # Should be >= 2.40 | |
| 12 | - | ||
| 13 | - | # Check Vulkan support (optional but recommended) | |
| 14 | - | vulkaninfo | grep "Vulkan Instance Version" | |
| 15 | - | ``` | |
| 16 | - | ||
| 17 | - | ### Install Dependencies (Arch Linux) | |
| 18 | - | ```bash | |
| 19 | - | sudo pacman -S webkit2gtk-6.0 gtk4 vulkan-tools | |
| 20 | - | ``` | |
| 21 | - | ||
| 22 | - | ### Install Dependencies (Ubuntu/Debian) | |
| 23 | - | ```bash | |
| 24 | - | sudo apt install libwebkitgtk-6.0-dev libgtk-4-dev vulkan-tools | |
| 25 | - | ``` | |
| 26 | - | ||
| 27 | - | ## Build and Test | |
| 28 | - | ||
| 29 | - | ### 1. Switch to Feature Branch | |
| 30 | - | ```bash | |
| 31 | - | git checkout 004-migrate-to-webkitgtk | |
| 32 | - | ``` | |
| 33 | - | ||
| 34 | - | ### 2. Build the Browser | |
| 35 | - | ```bash | |
| 36 | - | make clean | |
| 37 | - | make build | |
| 38 | - | ``` | |
| 39 | - | ||
| 40 | - | ### 3. Verify GPU Rendering | |
| 41 | - | ||
| 42 | - | #### Test Auto-Detection (Default) | |
| 43 | - | ```bash | |
| 44 | - | # Should auto-detect GPU availability | |
| 45 | - | ./dumber browse https://webglsamples.org/aquarium/aquarium.html | |
| 46 | - | ``` | |
| 47 | - | ||
| 48 | - | #### Force GPU Mode | |
| 49 | - | ```bash | |
| 50 | - | # Force GPU acceleration | |
| 51 | - | ./dumber browse --rendering-mode=gpu https://webglsamples.org/aquarium/aquarium.html | |
| 52 | - | ||
| 53 | - | # Or using environment variable | |
| 54 | - | DUMBER_RENDERING_MODE=gpu ./dumber browse https://example.com | |
| 55 | - | ``` | |
| 56 | - | ||
| 57 | - | #### Force CPU Mode | |
| 58 | - | ```bash | |
| 59 | - | # Force software rendering | |
| 60 | - | ./dumber browse --rendering-mode=cpu https://example.com | |
| 61 | - | ||
| 62 | - | # Or shorthand | |
| 63 | - | ./dumber browse --disable-gpu https://example.com | |
| 64 | - | ``` | |
| 65 | - | ||
| 66 | - | #### Debug GPU Compositing | |
| 67 | - | ```bash | |
| 68 | - | # Show GPU layer borders | |
| 69 | - | ./dumber browse --debug-gpu https://example.com | |
| 70 | - | ``` | |
| 71 | - | ||
| 72 | - | ### 4. Check Rendering Status | |
| 73 | - | ```bash | |
| 74 | - | # While browser is running, check status | |
| 75 | - | curl http://localhost:8080/api/rendering/status | |
| 76 | - | ``` | |
| 77 | - | ||
| 78 | - | Expected response: | |
| 79 | - | ```json | |
| 80 | - | { | |
| 81 | - | "mode": "auto", | |
| 82 | - | "gpu_active": true, | |
| 83 | - | "gpu_available": true, | |
| 84 | - | "vulkan_enabled": true, | |
| 85 | - | "errors": [], | |
| 86 | - | "performance": { | |
| 87 | - | "fps": 60, | |
| 88 | - | "cpu_usage_percent": 15.2, | |
| 89 | - | "gpu_usage_percent": 45.8, | |
| 90 | - | "memory_mb": 256 | |
| 91 | - | } | |
| 92 | - | } | |
| 93 | - | ``` | |
| 94 | - | ||
| 95 | - | ## Performance Testing | |
| 96 | - | ||
| 97 | - | ### 1. Benchmark Page Load | |
| 98 | - | ```bash | |
| 99 | - | # Measure with GPU | |
| 100 | - | time ./dumber browse --rendering-mode=gpu https://browserbench.org/MotionMark/ | |
| 101 | - | ||
| 102 | - | # Measure with CPU | |
| 103 | - | time ./dumber browse --rendering-mode=cpu https://browserbench.org/MotionMark/ | |
| 104 | - | ``` | |
| 105 | - | ||
| 106 | - | ### 2. Monitor Resource Usage | |
| 107 | - | ```bash | |
| 108 | - | # In another terminal, monitor GPU | |
| 109 | - | nvidia-smi -l 1 # For NVIDIA | |
| 110 | - | radeontop # For AMD | |
| 111 | - | ||
| 112 | - | # Monitor CPU | |
| 113 | - | htop | |
| 114 | - | ``` | |
| 115 | - | ||
| 116 | - | ### 3. Test WebGL Performance | |
| 117 | - | ```bash | |
| 118 | - | # High-demand WebGL test | |
| 119 | - | ./dumber browse https://webglsamples.org/dynamic-cubemap/dynamic-cubemap.html | |
| 120 | - | ||
| 121 | - | # Check FPS counter in browser | |
| 122 | - | ``` | |
| 123 | - | ||
| 124 | - | ## Troubleshooting | |
| 125 | - | ||
| 126 | - | ### GPU Not Detected | |
| 127 | - | ```bash | |
| 128 | - | # Check Vulkan drivers | |
| 129 | - | vulkaninfo | |
| 130 | - | ||
| 131 | - | # Check OpenGL | |
| 132 | - | glxinfo | grep "OpenGL renderer" | |
| 133 | - | ||
| 134 | - | # Force CPU mode if GPU issues | |
| 135 | - | ./dumber browse --disable-gpu | |
| 136 | - | ``` | |
| 137 | - | ||
| 138 | - | ### Performance Issues | |
| 139 | - | ```bash | |
| 140 | - | # Enable debug indicators | |
| 141 | - | ./dumber browse --debug-gpu https://example.com | |
| 142 | - | ||
| 143 | - | # Check for compositing issues (red borders = repaints) | |
| 144 | - | ``` | |
| 145 | - | ||
| 146 | - | ### Build Errors | |
| 147 | - | ```bash | |
| 148 | - | # Ensure correct pkg-config | |
| 149 | - | pkg-config --libs webkitgtk-6.0 gtk4 | |
| 150 | - | ||
| 151 | - | # Clean and rebuild | |
| 152 | - | make clean | |
| 153 | - | make build | |
| 154 | - | ``` | |
| 155 | - | ||
| 156 | - | ## Validation Checklist | |
| 157 | - | ||
| 158 | - | - [ ] Browser builds successfully with WebKitGTK 6.0 | |
| 159 | - | - [ ] Browser starts in < 500ms | |
| 160 | - | - [ ] GPU acceleration activates when available | |
| 161 | - | - [ ] CPU fallback works when GPU unavailable | |
| 162 | - | - [ ] WebGL content renders correctly | |
| 163 | - | - [ ] No visual artifacts or rendering issues | |
| 164 | - | - [ ] History and bookmarks preserved | |
| 165 | - | - [ ] All existing features work | |
| 166 | - | - [ ] Performance improved with GPU enabled | |
| 167 | - | - [ ] Resource usage within acceptable limits | |
| 168 | - | ||
| 169 | - | ## Migration Verification | |
| 170 | - | ||
| 171 | - | ### Check API Usage | |
| 172 | - | ```bash | |
| 173 | - | # Verify new GTK4/WebKit6 symbols | |
| 174 | - | ldd ./dumber | grep -E "(gtk-4|webkit.*6)" | |
| 175 | - | ||
| 176 | - | # Should see: | |
| 177 | - | # libgtk-4.so.1 | |
| 178 | - | # libwebkitgtk-6.0.so.4 | |
| 179 | - | ``` | |
| 180 | - | ||
| 181 | - | ### Test Key Features | |
| 182 | - | 1. **Navigation**: URLs load correctly | |
| 183 | - | 2. **History**: Previous data accessible | |
| 184 | - | 3. **Zoom**: Ctrl+Plus/Minus works | |
| 185 | - | 4. **DevTools**: F12 opens inspector | |
| 186 | - | 5. **Dmenu**: Integration still works | |
| 187 | - | ||
| 188 | - | ## Report Issues | |
| 189 | - | ||
| 190 | - | If you encounter issues: | |
| 191 | - | 1. Note the rendering mode used | |
| 192 | - | 2. Check `/tmp/dumber.log` for errors | |
| 193 | - | 3. Run with `--debug-gpu` for visual debugging | |
| 194 | - | 4. Report with output of `vulkaninfo` and `glxinfo`⏎̸ | |
D specs/004-migrate-to-webkitgtk/research.md +0 -115
| @@ -1,115 +0,0 @@ | |||
| 1 | - | # Research: WebKitGTK 6.0 Migration | |
| 2 | - | ||
| 3 | - | ## API Migration Research | |
| 4 | - | ||
| 5 | - | ### Decision: WebKitGTK 6.0 with GTK4 | |
| 6 | - | **Rationale**: | |
| 7 | - | - GTK4 provides native Vulkan renderer support | |
| 8 | - | - WebKitGTK 6.0 is the only actively maintained version for GTK4 | |
| 9 | - | - Enables hardware-accelerated rendering via modern GPU APIs | |
| 10 | - | - Better Wayland support and performance | |
| 11 | - | ||
| 12 | - | **Alternatives considered**: | |
| 13 | - | - Staying on WebKit2GTK 4.0: No Vulkan support, limited to OpenGL | |
| 14 | - | - Using WebKit2GTK 4.1: Still GTK3, no Vulkan renderer | |
| 15 | - | - Custom Vulkan implementation: Too complex, maintenance burden | |
| 16 | - | ||
| 17 | - | ### GTK3 to GTK4 Migration Patterns | |
| 18 | - | ||
| 19 | - | **Key Changes**: | |
| 20 | - | 1. **Event handling**: GdkEvent parameter removed from signals | |
| 21 | - | 2. **Widget construction**: Direct use of g_object_new() instead of specific constructors | |
| 22 | - | 3. **Drawing**: No more GtkDrawingArea draw signal, use GtkSnapshot | |
| 23 | - | 4. **CSS**: GTK4 uses standard CSS, removed custom properties | |
| 24 | - | 5. **Layout**: New layout managers replace containers | |
| 25 | - | ||
| 26 | - | **CGO Binding Updates**: | |
| 27 | - | - pkg-config: `webkit2gtk-4.0` → `webkitgtk-6.0` | |
| 28 | - | - pkg-config: `gtk+-3.0` → `gtk4` | |
| 29 | - | - Header: `gtk/gtk.h` remains same | |
| 30 | - | - Header: `webkit2/webkit2.h` → `webkit/webkit.h` | |
| 31 | - | ||
| 32 | - | ### Vulkan Renderer Configuration | |
| 33 | - | ||
| 34 | - | **Decision: Hardware Acceleration Policy** | |
| 35 | - | **Rationale**: Provides user control over GPU vs CPU rendering | |
| 36 | - | ||
| 37 | - | **Configuration Options**: | |
| 38 | - | 1. `WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS`: Force GPU | |
| 39 | - | 2. `WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER`: Force CPU | |
| 40 | - | 3. `WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND`: Auto-detect (default) | |
| 41 | - | ||
| 42 | - | **New Settings in WebKitGTK 6.0**: | |
| 43 | - | - `webkit_settings_set_hardware_acceleration_policy()` | |
| 44 | - | - `webkit_settings_set_enable_2d_canvas_acceleration()` | |
| 45 | - | - `webkit_settings_set_enable_webgl()` | |
| 46 | - | - `webkit_settings_set_draw_compositing_indicators()` (debugging) | |
| 47 | - | ||
| 48 | - | ### Deprecated APIs to Replace | |
| 49 | - | ||
| 50 | - | | WebKit2GTK 4.0 API | WebKitGTK 6.0 Replacement | | |
| 51 | - | |-------------------|---------------------------| | |
| 52 | - | | `webkit_web_view_new_with_context()` | `g_object_new()` with properties | | |
| 53 | - | | `webkit_web_context_set_sandbox_enabled()` | Always enabled, use `add_path_to_sandbox()` | | |
| 54 | - | | `WebKitWebContext` | `WebKitNetworkSession` for networking | | |
| 55 | - | | `webkit_web_view_run_javascript()` | Same, but async only | | |
| 56 | - | | Process swap property | Always enabled | | |
| 57 | - | ||
| 58 | - | ### Build System Changes | |
| 59 | - | ||
| 60 | - | **pkg-config flags**: | |
| 61 | - | ```bash | |
| 62 | - | # Old (WebKit2GTK 4.0) | |
| 63 | - | pkg-config --cflags --libs webkit2gtk-4.0 gtk+-3.0 javascriptcoregtk-4.0 | |
| 64 | - | ||
| 65 | - | # New (WebKitGTK 6.0) | |
| 66 | - | pkg-config --cflags --libs webkitgtk-6.0 gtk4 javascriptcoregtk-6.0 | |
| 67 | - | ``` | |
| 68 | - | ||
| 69 | - | ### Performance Considerations | |
| 70 | - | ||
| 71 | - | **GPU Rendering Benefits**: | |
| 72 | - | - Vulkan backend via GTK4's unified GPU renderer | |
| 73 | - | - Hardware-accelerated 2D canvas | |
| 74 | - | - Improved WebGL performance | |
| 75 | - | - Reduced CPU usage for compositing | |
| 76 | - | - Better multi-threaded rendering | |
| 77 | - | ||
| 78 | - | **Fallback Strategy**: | |
| 79 | - | - Detect GPU capabilities at runtime | |
| 80 | - | - Use `ON_DEMAND` policy for automatic selection | |
| 81 | - | - Provide config flag for manual override | |
| 82 | - | - Monitor performance metrics | |
| 83 | - | ||
| 84 | - | ### Global Rendering Configuration | |
| 85 | - | ||
| 86 | - | **Decision: Add RenderingMode to config** | |
| 87 | - | **Rationale**: User control over CPU/GPU rendering with smart defaults | |
| 88 | - | ||
| 89 | - | **Implementation**: | |
| 90 | - | ```go | |
| 91 | - | type RenderingMode string | |
| 92 | - | ||
| 93 | - | const ( | |
| 94 | - | RenderingModeAuto RenderingMode = "auto" // Default, detect at runtime | |
| 95 | - | RenderingModeGPU RenderingMode = "gpu" // Force GPU acceleration | |
| 96 | - | RenderingModeCPU RenderingMode = "cpu" // Force software rendering | |
| 97 | - | ) | |
| 98 | - | ``` | |
| 99 | - | ||
| 100 | - | **Config Integration**: | |
| 101 | - | - Add to `internal/config/config.go` | |
| 102 | - | - Default to "auto" (GPU if available) | |
| 103 | - | - CLI flag: `--rendering-mode=[auto|gpu|cpu]` | |
| 104 | - | - Environment variable: `DUMBER_RENDERING_MODE` | |
| 105 | - | ||
| 106 | - | ## Summary | |
| 107 | - | ||
| 108 | - | The migration to WebKitGTK 6.0 requires: | |
| 109 | - | 1. Complete GTK3 → GTK4 widget/event migration | |
| 110 | - | 2. Update all WebKit API calls to new versions | |
| 111 | - | 3. Implement hardware acceleration configuration | |
| 112 | - | 4. Add global rendering mode configuration | |
| 113 | - | 5. Test Vulkan renderer activation and fallback | |
| 114 | - | ||
| 115 | - | All technical questions have been resolved through research.⏎̸ | |
D specs/004-migrate-to-webkitgtk/spec.md +0 -111
| @@ -1,111 +0,0 @@ | |||
| 1 | - | # Feature Specification: Migrate to WebKitGTK 6.0 | |
| 2 | - | ||
| 3 | - | **Feature Branch**: `004-migrate-to-webkitgtk` | |
| 4 | - | **Created**: 2025-01-21 | |
| 5 | - | **Status**: Draft | |
| 6 | - | **Input**: User description: "Migrate To webkitgtk-6.0, I Want to migrate the entire project to webkitgtk6 in order to be able to enable GPU rendering through vulkan layer" | |
| 7 | - | ||
| 8 | - | ## Execution Flow (main) | |
| 9 | - | ``` | |
| 10 | - | 1. Parse user description from Input | |
| 11 | - | → Migrate browser to WebKitGTK 6.0 for Vulkan GPU rendering | |
| 12 | - | 2. Extract key concepts from description | |
| 13 | - | → Identified: migration, WebKitGTK 6.0, GPU rendering, Vulkan support | |
| 14 | - | 3. For each unclear aspect: | |
| 15 | - | → Performance targets marked for clarification | |
| 16 | - | → Migration timeline marked for clarification | |
| 17 | - | 4. Fill User Scenarios & Testing section | |
| 18 | - | → User flow: Browser continues to work with improved GPU performance | |
| 19 | - | 5. Generate Functional Requirements | |
| 20 | - | → Each requirement is testable | |
| 21 | - | → Migration scope defined | |
| 22 | - | 6. Identify Key Entities | |
| 23 | - | → Browser engine, rendering pipeline, GPU acceleration | |
| 24 | - | 7. Run Review Checklist | |
| 25 | - | → WARN "Spec has uncertainties around performance targets" | |
| 26 | - | 8. Return: SUCCESS (spec ready for planning) | |
| 27 | - | ``` | |
| 28 | - | ||
| 29 | - | --- | |
| 30 | - | ||
| 31 | - | ## ⚡ Quick Guidelines | |
| 32 | - | - ✅ Focus on WHAT users need and WHY | |
| 33 | - | - ❌ Avoid HOW to implement (no tech stack, APIs, code structure) | |
| 34 | - | - 👥 Written for business stakeholders, not developers | |
| 35 | - | ||
| 36 | - | --- | |
| 37 | - | ||
| 38 | - | ## User Scenarios & Testing | |
| 39 | - | ||
| 40 | - | ### Primary User Story | |
| 41 | - | As a user of the dumber browser, I want the browser to utilize modern GPU acceleration capabilities through Vulkan rendering, resulting in smoother scrolling, faster page rendering, and improved performance for graphics-intensive web content, while maintaining all existing browser functionality. | |
| 42 | - | ||
| 43 | - | ### Acceptance Scenarios | |
| 44 | - | 1. **Given** a user opens the browser, **When** they navigate to any website, **Then** the browser renders pages using GPU acceleration when available | |
| 45 | - | 2. **Given** a user visits a graphics-intensive website (e.g., with 3D content, animations), **When** the page loads, **Then** GPU rendering provides smooth performance without visual artifacts | |
| 46 | - | 3. **Given** a system with Vulkan-capable GPU, **When** the browser starts, **Then** it automatically detects and enables GPU acceleration | |
| 47 | - | 4. **Given** a system without Vulkan support, **When** the browser starts, **Then** it gracefully falls back to software rendering | |
| 48 | - | 5. **Given** the browser is using GPU acceleration, **When** monitoring system resources, **Then** CPU usage is reduced compared to software rendering | |
| 49 | - | ||
| 50 | - | ### Edge Cases | |
| 51 | - | - What happens when GPU drivers are outdated or incompatible? | |
| 52 | - | - How does system handle GPU driver crashes during browsing? | |
| 53 | - | - What happens on systems with multiple GPUs (integrated + discrete)? | |
| 54 | - | - How does browser perform on low-end GPUs vs high-end GPUs? | |
| 55 | - | - What happens when switching between GPU and software rendering mid-session? | |
| 56 | - | ||
| 57 | - | ## Requirements | |
| 58 | - | ||
| 59 | - | ### Functional Requirements | |
| 60 | - | - **FR-001**: System MUST maintain all existing browser functionality after migration | |
| 61 | - | - **FR-002**: System MUST support GPU-accelerated rendering when Vulkan-capable hardware is available | |
| 62 | - | - **FR-003**: System MUST provide fallback to software rendering when GPU acceleration is unavailable | |
| 63 | - | - **FR-004**: System MUST maintain backward compatibility with existing user data (bookmarks, history, settings) | |
| 64 | - | - **FR-005**: System MUST preserve current browser interface and user experience | |
| 65 | - | - **FR-006**: System MUST detect GPU capabilities at startup and choose appropriate rendering path | |
| 66 | - | - **FR-007**: System MUST handle GPU driver failures gracefully without crashing | |
| 67 | - | - **FR-008**: Browser performance MUST improve by [NEEDS CLARIFICATION: specific performance target not specified - 20%? 50%? What metrics?] | |
| 68 | - | - **FR-009**: System MUST support common web standards (HTML5, CSS3, JavaScript) without regression | |
| 69 | - | - **FR-010**: System MUST maintain support for all previously working websites | |
| 70 | - | - **FR-011**: GPU memory usage MUST remain within [NEEDS CLARIFICATION: acceptable limits not specified] | |
| 71 | - | - **FR-012**: Migration MUST be completed within [NEEDS CLARIFICATION: timeline not specified] | |
| 72 | - | ||
| 73 | - | ### Key Entities | |
| 74 | - | - **Browser Engine**: Core rendering engine that processes and displays web content | |
| 75 | - | - **GPU Rendering Pipeline**: System component responsible for hardware-accelerated graphics | |
| 76 | - | - **Fallback Renderer**: Software-based rendering system for non-GPU scenarios | |
| 77 | - | - **Performance Monitor**: Component tracking rendering performance and resource usage | |
| 78 | - | - **Compatibility Layer**: System ensuring existing functionality works with new rendering engine | |
| 79 | - | ||
| 80 | - | --- | |
| 81 | - | ||
| 82 | - | ## Review & Acceptance Checklist | |
| 83 | - | *GATE: Automated checks run during main() execution* | |
| 84 | - | ||
| 85 | - | ### Content Quality | |
| 86 | - | - [x] No implementation details (languages, frameworks, APIs) | |
| 87 | - | - [x] Focused on user value and business needs | |
| 88 | - | - [x] Written for non-technical stakeholders | |
| 89 | - | - [x] All mandatory sections completed | |
| 90 | - | ||
| 91 | - | ### Requirement Completeness | |
| 92 | - | - [ ] No [NEEDS CLARIFICATION] markers remain | |
| 93 | - | - [x] Requirements are testable and unambiguous (except marked items) | |
| 94 | - | - [ ] Success criteria are measurable (performance targets needed) | |
| 95 | - | - [x] Scope is clearly bounded | |
| 96 | - | - [x] Dependencies and assumptions identified | |
| 97 | - | ||
| 98 | - | --- | |
| 99 | - | ||
| 100 | - | ## Execution Status | |
| 101 | - | *Updated by main() during processing* | |
| 102 | - | ||
| 103 | - | - [x] User description parsed | |
| 104 | - | - [x] Key concepts extracted | |
| 105 | - | - [x] Ambiguities marked | |
| 106 | - | - [x] User scenarios defined | |
| 107 | - | - [x] Requirements generated | |
| 108 | - | - [x] Entities identified | |
| 109 | - | - [ ] Review checklist passed (has clarifications needed) | |
| 110 | - | ||
| 111 | - | ---⏎̸ | |
D specs/004-migrate-to-webkitgtk/tasks.md +0 -138
| @@ -1,138 +0,0 @@ | |||
| 1 | - | # Tasks: Migrate to WebKitGTK 6.0 | |
| 2 | - | ||
| 3 | - | **Input**: Design documents from `/specs/004-migrate-to-webkitgtk/` | |
| 4 | - | **Prerequisites**: plan.md (required), research.md, data-model.md, contracts/ | |
| 5 | - | ||
| 6 | - | ## Execution Flow (main) | |
| 7 | - | ``` | |
| 8 | - | 1. Load plan.md from feature directory | |
| 9 | - | → Loaded: WebKitGTK 6.0 migration plan | |
| 10 | - | → Extract: Go 1.25.1, WebKitGTK 6.0, GTK4, no TDD | |
| 11 | - | 2. Load optional design documents: | |
| 12 | - | → data-model.md: RenderingConfig model | |
| 13 | - | → contracts/: webkit-api.yaml, rendering-config.yaml | |
| 14 | - | → research.md: API migration mappings | |
| 15 | - | 3. Generate tasks by category: | |
| 16 | - | → Setup: Build config, dependencies | |
| 17 | - | → Core: Migrate webkit files incrementally | |
| 18 | - | → Integration: Rendering config, CLI flags | |
| 19 | - | → Verification: Test GPU acceleration | |
| 20 | - | 4. Apply task rules: | |
| 21 | - | → Different files = mark [P] for parallel | |
| 22 | - | → Same file = sequential (no [P]) | |
| 23 | - | → No TDD per user request | |
| 24 | - | 5. Number tasks sequentially (T001, T002...) | |
| 25 | - | 6. Generate dependency graph | |
| 26 | - | 7. Create parallel execution examples | |
| 27 | - | 8. Validate task completeness: | |
| 28 | - | → All webkit files migrated? | |
| 29 | - | → Rendering config implemented? | |
| 30 | - | → GPU acceleration verified? | |
| 31 | - | 9. Return: SUCCESS (tasks ready for execution) | |
| 32 | - | ``` | |
| 33 | - | ||
| 34 | - | ## Format: `[ID] [P?] Description` | |
| 35 | - | - **[P]**: Can run in parallel (different files, no dependencies) | |
| 36 | - | - Include exact file paths in descriptions | |
| 37 | - | ||
| 38 | - | ## Path Conventions | |
| 39 | - | - **Single project**: `pkg/webkit/` for WebKit bindings | |
| 40 | - | - **Config**: `internal/config/` for rendering configuration | |
| 41 | - | - **CLI**: `internal/cli/` for command-line flags | |
| 42 | - | ||
| 43 | - | ## Phase 3.1: Setup & Build Configuration | |
| 44 | - | - [ ] T001 Update pkg-config in all CGO files from webkit2gtk-4.0 to webkitgtk-6.0 | |
| 45 | - | - [ ] T002 Update GTK pkg-config from gtk+-3.0 to gtk4 in all CGO files | |
| 46 | - | - [ ] T003 Update JavaScript pkg-config from javascriptcoregtk-4.0 to javascriptcoregtk-6.0 | |
| 47 | - | - [ ] T004 Update Makefile build flags for GTK4/WebKitGTK 6.0 | |
| 48 | - | - [ ] T005 Verify build environment has GTK4 and WebKitGTK 6.0 installed | |
| 49 | - | ||
| 50 | - | ## Phase 3.2: Rendering Configuration | |
| 51 | - | - [ ] T006 [P] Add RenderingConfig struct to pkg/webkit/settings.go | |
| 52 | - | - [ ] T007 [P] Add RenderingMode constants and validation to internal/config/config.go | |
| 53 | - | - [ ] T008 [P] Add --rendering-mode CLI flag to internal/cli/browse.go | |
| 54 | - | - [ ] T009 [P] Add DUMBER_RENDERING_MODE environment variable support to internal/config/config.go | |
| 55 | - | ||
| 56 | - | ## Phase 3.3: Core WebKit Migration - Build Files | |
| 57 | - | - [ ] T010 [P] Migrate pkg/webkit/build_flags_cgo.go to WebKitGTK 6.0 headers | |
| 58 | - | - [ ] T011 [P] Migrate pkg/webkit/build_cgo_stub.go build tags for GTK4 | |
| 59 | - | - [ ] T012 [P] Update pkg/webkit/build_flags_stub.go for new build configuration | |
| 60 | - | ||
| 61 | - | ## Phase 3.4: Core WebKit Migration - Main Components | |
| 62 | - | - [ ] T013 Migrate pkg/webkit/webview_cgo.go - Update WebView creation to use g_object_new instead of webkit_web_view_new_with_context | |
| 63 | - | - [ ] T014 Migrate pkg/webkit/webview_cgo.go - Replace WebKitWebContext with WebKitNetworkSession | |
| 64 | - | - [ ] T015 Migrate pkg/webkit/webview_cgo.go - Add hardware acceleration policy settings | |
| 65 | - | - [ ] T016 Migrate pkg/webkit/window_cgo.go - Update gtk_window_new() without GTK_WINDOW_TOPLEVEL | |
| 66 | - | - [ ] T017 Migrate pkg/webkit/window_cgo.go - Replace gtk_container_add with gtk_window_set_child | |
| 67 | - | - [ ] T018 Migrate pkg/webkit/window_cgo.go - Update gtk_widget_destroy to gtk_window_destroy | |
| 68 | - | ||
| 69 | - | ## Phase 3.5: Core WebKit Migration - Event Handling | |
| 70 | - | - [ ] T019 Migrate pkg/webkit/keyboard_cgo.go - Replace GdkEventKey with GtkEventController | |
| 71 | - | - [ ] T020 Update pkg/webkit/keyboard_cgo.go - Migrate key-press-event to key-pressed signal | |
| 72 | - | - [ ] T021 Migrate button-press-event to GtkGestureClick in pkg/webkit/webview_cgo.go | |
| 73 | - | ||
| 74 | - | ## Phase 3.6: Feature Migration | |
| 75 | - | - [ ] T022 [P] Update pkg/webkit/script_cgo.go for GTK4 compatibility | |
| 76 | - | - [ ] T023 [P] Update pkg/webkit/zoom_cgo.go for GTK4 compatibility | |
| 77 | - | - [ ] T024 [P] Update pkg/webkit/devtools_cgo.go for GTK4 compatibility | |
| 78 | - | - [ ] T025 [P] Update pkg/webkit/loop_cgo.go for GTK4 main loop | |
| 79 | - | - [ ] T026 [P] Update pkg/webkit/scheme_cgo.go for new URI scheme handling | |
| 80 | - | ||
| 81 | - | ## Phase 3.7: Integration & Services | |
| 82 | - | - [ ] T027 Update services/browser_service.go to pass RenderingConfig to WebView | |
| 83 | - | - [ ] T028 Update services/config_service.go to handle rendering mode configuration | |
| 84 | - | - [ ] T029 Add GPU detection logic to determine auto mode in pkg/webkit/webview.go | |
| 85 | - | ||
| 86 | - | ## Phase 3.8: Testing & Verification | |
| 87 | - | - [ ] T030 Create test for GPU acceleration detection in tests/integration/test_gpu_rendering.go | |
| 88 | - | - [ ] T031 Create test for CPU fallback in tests/integration/test_cpu_fallback.go | |
| 89 | - | - [ ] T032 Update existing integration tests for GTK4 compatibility | |
| 90 | - | - [ ] T033 Manual test: Verify browser starts with GTK4/WebKitGTK 6.0 | |
| 91 | - | - [ ] T034 Manual test: Verify GPU acceleration with WebGL content | |
| 92 | - | - [ ] T035 Manual test: Verify CPU fallback with --rendering-mode=cpu | |
| 93 | - | ||
| 94 | - | ## Phase 3.9: Documentation & Cleanup | |
| 95 | - | - [ ] T036 [P] Update README.md with new build requirements | |
| 96 | - | - [ ] T037 [P] Document rendering mode configuration in docs/ | |
| 97 | - | - [ ] T038 Remove deprecated WebKit2GTK 4.0 compatibility code | |
| 98 | - | - [ ] T039 Update CLAUDE.md to reflect completed migration | |
| 99 | - | ||
| 100 | - | ## Dependencies | |
| 101 | - | - Build config (T001-T005) must complete first | |
| 102 | - | - Rendering config (T006-T009) can run in parallel | |
| 103 | - | - Core migration (T010-T026) depends on build config | |
| 104 | - | - T013-T015 must be sequential (same file) | |
| 105 | - | - T016-T018 must be sequential (same file) | |
| 106 | - | - Integration (T027-T029) depends on core migration | |
| 107 | - | - Testing (T030-T035) depends on all implementation | |
| 108 | - | - Documentation (T036-T039) can start anytime | |
| 109 | - | ||
| 110 | - | ## Parallel Example | |
| 111 | - | ```bash | |
| 112 | - | # Launch T006-T009 together (different files): | |
| 113 | - | Task: "Add RenderingConfig struct to pkg/webkit/settings.go" | |
| 114 | - | Task: "Add RenderingMode constants to internal/config/config.go" | |
| 115 | - | Task: "Add --rendering-mode CLI flag to internal/cli/browse.go" | |
| 116 | - | Task: "Add DUMBER_RENDERING_MODE env var to internal/config/config.go" | |
| 117 | - | ||
| 118 | - | # Launch T022-T026 together (independent files): | |
| 119 | - | Task: "Update pkg/webkit/script_cgo.go for GTK4" | |
| 120 | - | Task: "Update pkg/webkit/zoom_cgo.go for GTK4" | |
| 121 | - | Task: "Update pkg/webkit/devtools_cgo.go for GTK4" | |
| 122 | - | Task: "Update pkg/webkit/loop_cgo.go for GTK4" | |
| 123 | - | Task: "Update pkg/webkit/scheme_cgo.go for URI handling" | |
| 124 | - | ``` | |
| 125 | - | ||
| 126 | - | ## Notes | |
| 127 | - | - No TDD per user request - migrate first, test after | |
| 128 | - | - Focus on incremental file-by-file migration | |
| 129 | - | - Test GPU acceleration after each major component | |
| 130 | - | - Commit after each task to track progress | |
| 131 | - | - Use quickstart.md for verification steps | |
| 132 | - | ||
| 133 | - | ## Critical Migration Points | |
| 134 | - | 1. **WebView Creation**: Must update to g_object_new pattern | |
| 135 | - | 2. **Network Session**: Replace all WebContext usage | |
| 136 | - | 3. **Event Handling**: GTK4 uses controllers not direct events | |
| 137 | - | 4. **Container API**: gtk_container_add no longer exists | |
| 138 | - | 5. **Hardware Acceleration**: Must configure policy correctly⏎̸ | |
D specs/005-webkit-memory-optimization/contracts/webkit_memory_api.go +0 -184
| @@ -1,184 +0,0 @@ | |||
| 1 | - | // Package contracts defines the WebKit memory optimization API contracts | |
| 2 | - | // This file contains the expected function signatures and behavior contracts | |
| 3 | - | package contracts | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "time" | |
| 7 | - | "unsafe" | |
| 8 | - | ) | |
| 9 | - | ||
| 10 | - | // WebKitMemoryAPI defines the contract for WebKit memory management functions | |
| 11 | - | type WebKitMemoryAPI interface { | |
| 12 | - | // Memory Pressure Settings | |
| 13 | - | CreateMemoryPressureSettings(memoryLimitMB int, conservativeThreshold, strictThreshold, killThreshold, pollInterval float64) (unsafe.Pointer, error) | |
| 14 | - | ApplyMemoryPressureSettings(context unsafe.Pointer, settings unsafe.Pointer) error | |
| 15 | - | ||
| 16 | - | // Cache Model Management | |
| 17 | - | SetCacheModel(context unsafe.Pointer, model CacheModel) error | |
| 18 | - | GetCurrentCacheModel(context unsafe.Pointer) (CacheModel, error) | |
| 19 | - | ||
| 20 | - | // JavaScript Garbage Collection | |
| 21 | - | TriggerJavaScriptGC(context unsafe.Pointer) error | |
| 22 | - | ||
| 23 | - | // WebView Settings | |
| 24 | - | SetPageCacheEnabled(settings unsafe.Pointer, enabled bool) error | |
| 25 | - | SetOfflineAppCacheEnabled(settings unsafe.Pointer, enabled bool) error | |
| 26 | - | ||
| 27 | - | // Memory Monitoring | |
| 28 | - | GetProcessMemoryInfo(pid int) (ProcessMemoryInfo, error) | |
| 29 | - | ListWebKitProcesses() ([]ProcessMemoryInfo, error) | |
| 30 | - | } | |
| 31 | - | ||
| 32 | - | // CacheModel represents WebKit cache model options | |
| 33 | - | type CacheModel int | |
| 34 | - | ||
| 35 | - | const ( | |
| 36 | - | CacheModelDocumentViewer CacheModel = iota | |
| 37 | - | CacheModelWebBrowser | |
| 38 | - | CacheModelPrimaryWebBrowser | |
| 39 | - | ) | |
| 40 | - | ||
| 41 | - | // ProcessMemoryInfo represents process memory statistics | |
| 42 | - | type ProcessMemoryInfo struct { | |
| 43 | - | PID int `json:"pid"` | |
| 44 | - | VmRSS int64 `json:"vm_rss"` // KB | |
| 45 | - | VmSize int64 `json:"vm_size"` // KB | |
| 46 | - | VmPeak int64 `json:"vm_peak"` // KB | |
| 47 | - | ProcessName string `json:"process_name"` | |
| 48 | - | } | |
| 49 | - | ||
| 50 | - | // MemoryConfigAPI defines the contract for memory configuration management | |
| 51 | - | type MemoryConfigAPI interface { | |
| 52 | - | // Configuration Validation | |
| 53 | - | ValidateMemoryConfig(config MemoryConfig) error | |
| 54 | - | ||
| 55 | - | // Preset Management | |
| 56 | - | GetMemoryOptimizedPreset() MemoryConfig | |
| 57 | - | GetBalancedPreset() MemoryConfig | |
| 58 | - | GetHighPerformancePreset() MemoryConfig | |
| 59 | - | ||
| 60 | - | // Configuration Application | |
| 61 | - | ApplyMemoryConfig(webview unsafe.Pointer, config MemoryConfig) error | |
| 62 | - | } | |
| 63 | - | ||
| 64 | - | // MemoryConfig represents memory optimization configuration | |
| 65 | - | type MemoryConfig struct { | |
| 66 | - | MemoryLimitMB int `json:"memory_limit_mb"` | |
| 67 | - | ConservativeThreshold float64 `json:"conservative_threshold"` | |
| 68 | - | StrictThreshold float64 `json:"strict_threshold"` | |
| 69 | - | KillThreshold float64 `json:"kill_threshold"` | |
| 70 | - | PollIntervalSeconds float64 `json:"poll_interval_seconds"` | |
| 71 | - | CacheModel string `json:"cache_model"` | |
| 72 | - | EnablePageCache bool `json:"enable_page_cache"` | |
| 73 | - | EnableOfflineAppCache bool `json:"enable_offline_app_cache"` | |
| 74 | - | ProcessRecycleThreshold int `json:"process_recycle_threshold"` | |
| 75 | - | EnableGCInterval int `json:"enable_gc_interval"` | |
| 76 | - | EnableMemoryMonitoring bool `json:"enable_memory_monitoring"` | |
| 77 | - | } | |
| 78 | - | ||
| 79 | - | // MemoryStatsAPI defines the contract for memory statistics tracking | |
| 80 | - | type MemoryStatsAPI interface { | |
| 81 | - | // Statistics Retrieval | |
| 82 | - | GetMemoryStats(webviewID uintptr) (MemoryStats, error) | |
| 83 | - | GetAllMemoryStats() (map[uintptr]MemoryStats, error) | |
| 84 | - | ||
| 85 | - | // Memory Management Operations | |
| 86 | - | TriggerMemoryCleanup(webviewID uintptr) error | |
| 87 | - | ShouldRecycleWebView(webviewID uintptr) (bool, error) | |
| 88 | - | ||
| 89 | - | // Monitoring Operations | |
| 90 | - | StartMemoryMonitoring(interval time.Duration) error | |
| 91 | - | StopMemoryMonitoring() error | |
| 92 | - | GetTotalMemoryUsage() (float64, error) // MB | |
| 93 | - | } | |
| 94 | - | ||
| 95 | - | // MemoryStats represents WebView memory statistics | |
| 96 | - | type MemoryStats struct { | |
| 97 | - | PageLoadCount int `json:"page_load_count"` | |
| 98 | - | LastGCTime time.Time `json:"last_gc_time"` | |
| 99 | - | HasMemoryPressureSettings bool `json:"has_memory_pressure_settings"` | |
| 100 | - | WebViewID uintptr `json:"webview_id"` | |
| 101 | - | } | |
| 102 | - | ||
| 103 | - | // WebViewLifecycleAPI defines the contract for WebView lifecycle management | |
| 104 | - | type WebViewLifecycleAPI interface { | |
| 105 | - | // WebView Registration | |
| 106 | - | RegisterWebView(webviewID uintptr, config MemoryConfig) error | |
| 107 | - | UnregisterWebView(webviewID uintptr) error | |
| 108 | - | ||
| 109 | - | // Lifecycle Events | |
| 110 | - | OnPageLoad(webviewID uintptr, url string) error | |
| 111 | - | OnMemoryPressure(webviewID uintptr, pressureLevel int) error | |
| 112 | - | OnGarbageCollection(webviewID uintptr) error | |
| 113 | - | ||
| 114 | - | // Recycling Operations | |
| 115 | - | ShouldRecycleWebView(webviewID uintptr) bool | |
| 116 | - | RequestWebViewRecycling(webviewID uintptr) error | |
| 117 | - | } | |
| 118 | - | ||
| 119 | - | // Error Types - define expected error behaviors | |
| 120 | - | ||
| 121 | - | // ErrMemoryLimitExceeded indicates memory usage exceeded configured limits | |
| 122 | - | type ErrMemoryLimitExceeded struct { | |
| 123 | - | Limit int64 // bytes | |
| 124 | - | Actual int64 // bytes | |
| 125 | - | } | |
| 126 | - | ||
| 127 | - | func (e ErrMemoryLimitExceeded) Error() string { | |
| 128 | - | return "memory limit exceeded" | |
| 129 | - | } | |
| 130 | - | ||
| 131 | - | // ErrInvalidMemoryConfig indicates invalid memory configuration parameters | |
| 132 | - | type ErrInvalidMemoryConfig struct { | |
| 133 | - | Field string | |
| 134 | - | Message string | |
| 135 | - | } | |
| 136 | - | ||
| 137 | - | func (e ErrInvalidMemoryConfig) Error() string { | |
| 138 | - | return "invalid memory configuration" | |
| 139 | - | } | |
| 140 | - | ||
| 141 | - | // ErrWebKitAPIUnavailable indicates WebKit memory APIs are not available | |
| 142 | - | type ErrWebKitAPIUnavailable struct { | |
| 143 | - | Function string | |
| 144 | - | Reason string | |
| 145 | - | } | |
| 146 | - | ||
| 147 | - | func (e ErrWebKitAPIUnavailable) Error() string { | |
| 148 | - | return "WebKit API unavailable" | |
| 149 | - | } | |
| 150 | - | ||
| 151 | - | // Behavioral Contracts - define expected behaviors as comments | |
| 152 | - | ||
| 153 | - | /* | |
| 154 | - | MEMORY_PRESSURE_CONTRACT: | |
| 155 | - | - Conservative threshold (0.2) should trigger background cleanup | |
| 156 | - | - Strict threshold (0.35) should trigger aggressive cleanup | |
| 157 | - | - Kill threshold (0.8) should trigger process termination warning | |
| 158 | - | - Poll interval determines monitoring frequency (2.0s recommended) | |
| 159 | - | - Memory limit applies per-WebView instance, not global | |
| 160 | - | ||
| 161 | - | CACHE_MODEL_CONTRACT: | |
| 162 | - | - DocumentViewer: Minimal caching, ~40% less memory than WebBrowser | |
| 163 | - | - WebBrowser: Default caching, balanced performance/memory | |
| 164 | - | - PrimaryWebBrowser: Maximum caching, highest memory usage | |
| 165 | - | - Changes take effect on next navigation | |
| 166 | - | ||
| 167 | - | GC_CONTRACT: | |
| 168 | - | - JavaScript GC triggers should complete within 2 seconds | |
| 169 | - | - GC should not block UI thread or navigation | |
| 170 | - | - Periodic GC intervals should be 30-120 seconds for effectiveness | |
| 171 | - | - Manual GC triggers should be idempotent (safe to call repeatedly) | |
| 172 | - | ||
| 173 | - | PROCESS_RECYCLING_CONTRACT: | |
| 174 | - | - Page load counting should be accurate and monotonic | |
| 175 | - | - Recycling recommendations should not force immediate action | |
| 176 | - | - New WebView creation should reset all memory counters | |
| 177 | - | - Recycling should preserve user session state until destruction | |
| 178 | - | ||
| 179 | - | MONITORING_CONTRACT: | |
| 180 | - | - Memory statistics should be updated within poll interval | |
| 181 | - | - /proc parsing should handle process disappearance gracefully | |
| 182 | - | - Memory reporting should be accurate within 5% of system tools | |
| 183 | - | - Monitoring overhead should be <1% of total browser memory usage | |
| 184 | - | */ | |
D specs/005-webkit-memory-optimization/data-model.md +0 -185
| @@ -1,185 +0,0 @@ | |||
| 1 | - | # Data Model: WebKit Memory Optimization | |
| 2 | - | ||
| 3 | - | **Feature**: 005-webkit-memory-optimization | |
| 4 | - | **Phase**: 1 - Design & Data Model | |
| 5 | - | **Date**: 2025-01-10 | |
| 6 | - | ||
| 7 | - | ## Core Entities | |
| 8 | - | ||
| 9 | - | ### MemoryConfig | |
| 10 | - | **Purpose**: Configuration settings that control WebKit memory optimization behavior | |
| 11 | - | ||
| 12 | - | **Fields**: | |
| 13 | - | - `MemoryLimitMB` (int): Maximum memory limit per WebView in MB (0 = unlimited) | |
| 14 | - | - `ConservativeThreshold` (float64): Early memory cleanup threshold (0.0-1.0, default 0.33) | |
| 15 | - | - `StrictThreshold` (float64): Aggressive memory cleanup threshold (0.0-1.0, default 0.5) | |
| 16 | - | - `KillThreshold` (float64): Process termination threshold (0.0-1.0, 0 = disabled) | |
| 17 | - | - `PollIntervalSeconds` (float64): Memory usage polling interval (default 2.0) | |
| 18 | - | - `CacheModel` (CacheModel): WebKit caching strategy (document_viewer/web_browser/primary_web_browser) | |
| 19 | - | - `EnablePageCache` (bool): Enable/disable page cache for back/forward navigation | |
| 20 | - | - `EnableOfflineAppCache` (bool): Enable/disable offline application caching | |
| 21 | - | - `ProcessRecycleThreshold` (int): Recycle WebView after N page loads (0 = disabled) | |
| 22 | - | - `EnableGCInterval` (int): JavaScript garbage collection interval in seconds (0 = disabled) | |
| 23 | - | - `EnableMemoryMonitoring` (bool): Enable detailed memory logging and monitoring | |
| 24 | - | ||
| 25 | - | **Validation Rules**: | |
| 26 | - | - ConservativeThreshold must be between 0.0 and 1.0 | |
| 27 | - | - StrictThreshold must be between 0.0 and 1.0 | |
| 28 | - | - StrictThreshold must be greater than ConservativeThreshold | |
| 29 | - | - KillThreshold must be between 0.0 and 1.0 | |
| 30 | - | - PollIntervalSeconds must be non-negative | |
| 31 | - | - MemoryLimitMB must be non-negative | |
| 32 | - | ||
| 33 | - | **State Transitions**: Immutable configuration object (changes require new instance) | |
| 34 | - | ||
| 35 | - | ### MemoryStats | |
| 36 | - | **Purpose**: Real-time and historical memory usage statistics for WebView instances | |
| 37 | - | ||
| 38 | - | **Fields**: | |
| 39 | - | - `pageLoadCount` (int): Number of pages loaded in this WebView instance | |
| 40 | - | - `lastGCTime` (time.Time): Timestamp of last JavaScript garbage collection | |
| 41 | - | - `memoryPressureSettings` (*C.WebKitMemoryPressureSettings): Native WebKit memory settings | |
| 42 | - | ||
| 43 | - | **Relationships**: | |
| 44 | - | - Owned by WebView instance (1:1 relationship) | |
| 45 | - | - References native WebKit memory pressure settings | |
| 46 | - | - Tracked by WebViewMemoryManager (many:1 relationship) | |
| 47 | - | ||
| 48 | - | **Validation Rules**: Read-only statistics, no validation required | |
| 49 | - | ||
| 50 | - | **State Transitions**: | |
| 51 | - | - `pageLoadCount` increments on each page load | |
| 52 | - | - `lastGCTime` updates when garbage collection is triggered | |
| 53 | - | - `memoryPressureSettings` set once during WebView creation | |
| 54 | - | ||
| 55 | - | ### ProcessMemoryInfo | |
| 56 | - | **Purpose**: System-level memory information for WebKit processes | |
| 57 | - | ||
| 58 | - | **Fields**: | |
| 59 | - | - `PID` (int): Process identifier | |
| 60 | - | - `VmRSS` (int64): Resident Set Size in KB (actual RAM usage) | |
| 61 | - | - `VmSize` (int64): Virtual Memory Size in KB (total virtual memory) | |
| 62 | - | - `VmPeak` (int64): Peak Virtual Memory in KB (maximum ever used) | |
| 63 | - | - `ProcessName` (string): Name of the process (extracted from cmdline) | |
| 64 | - | ||
| 65 | - | **Relationships**: | |
| 66 | - | - Collected by WebViewMemoryManager for all WebKit processes | |
| 67 | - | - Associated with specific WebView instances (many:1 for multi-process WebKit) | |
| 68 | - | ||
| 69 | - | **Validation Rules**: | |
| 70 | - | - All memory values must be non-negative | |
| 71 | - | - PID must be positive integer | |
| 72 | - | ||
| 73 | - | **State Transitions**: Immutable snapshot of process memory state | |
| 74 | - | ||
| 75 | - | ### OptimizationPreset | |
| 76 | - | **Purpose**: Pre-configured memory optimization settings for common use cases | |
| 77 | - | ||
| 78 | - | **Fields**: Embeds MemoryConfig with preset values | |
| 79 | - | ||
| 80 | - | **Preset Types**: | |
| 81 | - | 1. **MemoryOptimized**: Maximum memory reduction (256MB limit, aggressive thresholds) | |
| 82 | - | 2. **Balanced**: Moderate optimization (512MB limit, balanced thresholds) | |
| 83 | - | 3. **HighPerformance**: Maximum performance (no limits, minimal optimization) | |
| 84 | - | ||
| 85 | - | **Validation Rules**: Inherits MemoryConfig validation rules | |
| 86 | - | ||
| 87 | - | **State Transitions**: Immutable preset definitions | |
| 88 | - | ||
| 89 | - | ### WebViewMemoryManager | |
| 90 | - | **Purpose**: Global memory monitoring and lifecycle management for multiple WebViews | |
| 91 | - | ||
| 92 | - | **Fields**: | |
| 93 | - | - `views` (map[uintptr]*WebView): Registry of active WebViews by ID | |
| 94 | - | - `enableMonitoring` (bool): Enable background memory monitoring | |
| 95 | - | - `recycleThreshold` (int): Global recycling threshold | |
| 96 | - | - `monitoringInterval` (time.Duration): Monitoring check frequency | |
| 97 | - | - `stopMonitoring` (chan struct{}): Channel for stopping monitoring goroutine | |
| 98 | - | ||
| 99 | - | **Relationships**: | |
| 100 | - | - Manages multiple WebView instances (1:many) | |
| 101 | - | - Monitors ProcessMemoryInfo for all WebKit processes | |
| 102 | - | - Singleton pattern for global memory management | |
| 103 | - | ||
| 104 | - | **Validation Rules**: | |
| 105 | - | - monitoringInterval must be positive | |
| 106 | - | - recycleThreshold must be non-negative | |
| 107 | - | ||
| 108 | - | **State Transitions**: | |
| 109 | - | - WebViews registered on creation, unregistered on destruction | |
| 110 | - | - Monitoring starts when first WebView registered | |
| 111 | - | - Monitoring stops when last WebView unregistered | |
| 112 | - | ||
| 113 | - | ## Entity Relationships | |
| 114 | - | ||
| 115 | - | ``` | |
| 116 | - | WebView (1) ----owns----> (1) MemoryStats | |
| 117 | - | | | | |
| 118 | - | | | | |
| 119 | - | v v | |
| 120 | - | WebViewMemoryManager <-tracks- ProcessMemoryInfo | |
| 121 | - | | | |
| 122 | - | | | |
| 123 | - | v (configures) | |
| 124 | - | MemoryConfig <-preset- OptimizationPreset | |
| 125 | - | ``` | |
| 126 | - | ||
| 127 | - | ## Data Flow | |
| 128 | - | ||
| 129 | - | ### Memory Configuration Flow | |
| 130 | - | 1. User selects optimization preset or custom settings | |
| 131 | - | 2. MemoryConfig validated and applied to WebView creation | |
| 132 | - | 3. WebKit memory pressure settings configured via C API | |
| 133 | - | 4. Settings persisted for process lifecycle | |
| 134 | - | ||
| 135 | - | ### Memory Monitoring Flow | |
| 136 | - | 1. WebViewMemoryManager polls /proc filesystem for process memory | |
| 137 | - | 2. WebKit memory pressure callbacks trigger on internal events | |
| 138 | - | 3. MemoryStats updated with current usage and GC events | |
| 139 | - | 4. Memory events logged if monitoring enabled | |
| 140 | - | ||
| 141 | - | ### Process Recycling Flow | |
| 142 | - | 1. MemoryStats.pageLoadCount incremented on navigation | |
| 143 | - | 2. WebViewMemoryManager checks recycling threshold | |
| 144 | - | 3. Recycling recommendation logged (user/application decision) | |
| 145 | - | 4. New WebView creation triggers fresh memory allocation | |
| 146 | - | ||
| 147 | - | ## Memory Layout Considerations | |
| 148 | - | ||
| 149 | - | ### Go Memory Management | |
| 150 | - | - WebView structs include finalizers for cleanup | |
| 151 | - | - CGO memory requires explicit free() calls | |
| 152 | - | - Channel-based coordination for goroutine cleanup | |
| 153 | - | - Careful pointer management for C callbacks | |
| 154 | - | ||
| 155 | - | ### WebKit Native Memory | |
| 156 | - | - WebKitMemoryPressureSettings allocated via C API | |
| 157 | - | - GObject reference counting for WebKit objects | |
| 158 | - | - Memory pressure thresholds enforced by WebKit internally | |
| 159 | - | - Process memory isolated per WebView instance | |
| 160 | - | ||
| 161 | - | ### Monitoring Memory Overhead | |
| 162 | - | - /proc parsing: ~1KB per process check | |
| 163 | - | - Memory statistics storage: ~100 bytes per WebView | |
| 164 | - | - Monitoring goroutine: ~8KB stack space | |
| 165 | - | - Logging overhead: configurable via EnableMemoryMonitoring flag | |
| 166 | - | ||
| 167 | - | ## Testing Considerations | |
| 168 | - | ||
| 169 | - | ### Unit Tests | |
| 170 | - | - MemoryConfig validation rules | |
| 171 | - | - OptimizationPreset value correctness | |
| 172 | - | - ProcessMemoryInfo parsing accuracy | |
| 173 | - | - WebViewMemoryManager lifecycle management | |
| 174 | - | ||
| 175 | - | ### Integration Tests | |
| 176 | - | - WebKit memory pressure settings application | |
| 177 | - | - Real memory usage reduction measurement | |
| 178 | - | - Process recycling effectiveness | |
| 179 | - | - Memory monitoring accuracy vs /proc ground truth | |
| 180 | - | ||
| 181 | - | ### Contract Tests | |
| 182 | - | - WebKit C API memory functions available | |
| 183 | - | - Memory pressure callbacks functional | |
| 184 | - | - GObject reference counting correct | |
| 185 | - | - CGO memory safety verified⏎̸ | |
D specs/005-webkit-memory-optimization/plan.md +0 -259
| @@ -1,259 +0,0 @@ | |||
| 1 | - | # Implementation Plan: WebKit Memory Optimization | |
| 2 | - | ||
| 3 | - | **Branch**: `005-webkit-memory-optimization` | **Date**: 2025-01-10 | **Spec**: [spec.md](./spec.md) | |
| 4 | - | **Input**: Feature specification from `/specs/005-webkit-memory-optimization/spec.md` | |
| 5 | - | ||
| 6 | - | ## Execution Flow (/plan command scope) | |
| 7 | - | ``` | |
| 8 | - | 1. Load feature spec from Input path | |
| 9 | - | → If not found: ERROR "No feature spec at {path}" | |
| 10 | - | 2. Fill Technical Context (scan for NEEDS CLARIFICATION) | |
| 11 | - | → Detect Project Type from context (web=frontend+backend, mobile=app+api) | |
| 12 | - | → Set Structure Decision based on project type | |
| 13 | - | 3. Evaluate Constitution Check section below | |
| 14 | - | → If violations exist: Document in Complexity Tracking | |
| 15 | - | → If no justification possible: ERROR "Simplify approach first" | |
| 16 | - | → Update Progress Tracking: Initial Constitution Check | |
| 17 | - | 4. Execute Phase 0 → research.md | |
| 18 | - | → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns" | |
| 19 | - | 5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI). | |
| 20 | - | 6. Re-evaluate Constitution Check section | |
| 21 | - | → If new violations: Refactor design, return to Phase 1 | |
| 22 | - | → Update Progress Tracking: Post-Design Constitution Check | |
| 23 | - | 7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) | |
| 24 | - | 8. STOP - Ready for /tasks command | |
| 25 | - | ``` | |
| 26 | - | ||
| 27 | - | **IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands: | |
| 28 | - | - Phase 2: /tasks command creates tasks.md | |
| 29 | - | - Phase 3-4: Implementation execution (manual or via tools) | |
| 30 | - | ||
| 31 | - | ## Summary | |
| 32 | - | **Primary Requirement**: Reduce WebKit browser memory usage from ~400MB to 150-250MB per instance (40-60% reduction) while maintaining browser stability and essential functionality. | |
| 33 | - | ||
| 34 | - | **Technical Approach**: Implement WebKit memory pressure settings, optimize cache models, add periodic JavaScript garbage collection, enable process recycling, and provide configurable memory optimization presets for different usage scenarios. | |
| 35 | - | ||
| 36 | - | ## What’s Implemented So Far | |
| 37 | - | Based on current branch diffs (uncommitted changes): | |
| 38 | - | - Config: Added `MemoryConfig` to `pkg/webkit/settings.go` with thresholds, cache model, GC interval, page/offline cache toggles, monitoring, and recycling. | |
| 39 | - | - WebKit integration (`pkg/webkit/webview_cgo.go`): | |
| 40 | - | - Applies `WebKitMemoryPressureSettings` (limit, thresholds, poll interval) to default `WebContext`. | |
| 41 | - | - Sets cache model (DocumentViewer/WebBrowser/Primary). | |
| 42 | - | - Toggles page cache and offline app cache. | |
| 43 | - | - Adds periodic JavaScript GC (ticker) and manual cleanup. | |
| 44 | - | - Tracks memory stats (page loads, last GC), exposes `GetMemoryStats()`. | |
| 45 | - | - Counts page loads and logs when recycle threshold is reached. | |
| 46 | - | - Hooks WebViews into a global memory manager when monitoring enabled. | |
| 47 | - | - Memory manager (`pkg/webkit/memory.go`): | |
| 48 | - | - Scans `/proc` for WebKit-related processes, parses memory (`VmRSS`, `VmSize`, `VmPeak`). | |
| 49 | - | - Provides totals, detailed info, and recycling recommendation helpers. | |
| 50 | - | - Global manager lifecycle with background monitoring ticker. | |
| 51 | - | - Presets and validation (`pkg/webkit/memory_example.go`): Memory-optimized, Balanced, High-performance configs and `ValidateMemoryConfig`. | |
| 52 | - | ||
| 53 | - | Observations: | |
| 54 | - | - Implementation aligns with spec goals: limits, cache tuning, GC, monitoring, and recycling are in place. | |
| 55 | - | - Tests exist but are placeholders; contract/integration coverage for memory features is still missing. | |
| 56 | - | ||
| 57 | - | ## Technical Context | |
| 58 | - | **Language/Version**: Go 1.25.1 with CGO (WebKit2GTK 6.0 bindings) | |
| 59 | - | **Primary Dependencies**: WebKit2GTK 6.0, GTK4, JavaScriptCoreGTK 6.0, GLib/GObject | |
| 60 | - | **Storage**: Configuration files (memory settings), /proc filesystem (memory monitoring) | |
| 61 | - | **Testing**: Go testing framework, contract tests for WebKit memory APIs, integration tests with real WebKit processes | |
| 62 | - | **Target Platform**: Linux (Wayland/X11) with WebKit2GTK 6.0+ system packages | |
| 63 | - | **Project Type**: single (WebKit browser enhancement) | |
| 64 | - | **Performance Goals**: 40-60% memory reduction (400MB → 150-250MB), <2s garbage collection impact, <500ms startup overhead | |
| 65 | - | **Constraints**: Maintain browser stability, preserve essential web functionality, no performance degradation >20% | |
| 66 | - | **Scale/Scope**: Single WebView instances, multiple browser windows, up to 100+ page loads per process lifecycle | |
| 67 | - | ||
| 68 | - | ## Constitution Check | |
| 69 | - | *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | |
| 70 | - | ||
| 71 | - | **Simplicity**: | |
| 72 | - | - Projects: 1 (enhancing existing webkit package - no new projects) | |
| 73 | - | - Using framework directly? YES (WebKit2GTK C APIs via CGO) | |
| 74 | - | - Single data model? YES (MemoryConfig and MemoryStats structs) | |
| 75 | - | - Avoiding patterns? YES (direct WebKit API calls, no abstraction layers) | |
| 76 | - | ||
| 77 | - | **Architecture**: | |
| 78 | - | - EVERY feature as library? PARTIAL (webkit package is library, memory features enhance it) | |
| 79 | - | - Libraries listed: pkg/webkit (WebKit2GTK Go bindings + memory optimization) | |
| 80 | - | - CLI per library: N/A (browser features, not CLI commands) | |
| 81 | - | - Library docs: Will update CLAUDE.md with memory optimization context | |
| 82 | - | ||
| 83 | - | **Testing (NON-NEGOTIABLE)**: | |
| 84 | - | - RED-GREEN-Refactor cycle enforced? YES (tests for memory limits, GC triggers, monitoring) | |
| 85 | - | - Git commits show tests before implementation? YES (TDD approach planned) | |
| 86 | - | - Order: Contract→Integration→E2E→Unit strictly followed? YES | |
| 87 | - | - Real dependencies used? YES (actual WebKit processes, real memory monitoring) | |
| 88 | - | - Integration tests for: YES (memory pressure settings, process recycling, GC effectiveness) | |
| 89 | - | - FORBIDDEN: Implementation before test, skipping RED phase | |
| 90 | - | ||
| 91 | - | **Observability**: | |
| 92 | - | - Structured logging included? YES (using Go log package with memory monitoring flags) | |
| 93 | - | - Frontend logs → backend? N/A (single process browser) | |
| 94 | - | - Error context sufficient? YES (memory pressure events, GC failures, recycling triggers) | |
| 95 | - | ||
| 96 | - | **Versioning**: | |
| 97 | - | - Version number assigned? 005 (feature number, follows existing pattern) | |
| 98 | - | - BUILD increments on every change? YES (follows project build process) | |
| 99 | - | - Breaking changes handled? YES (backwards compatible config with defaults) | |
| 100 | - | ||
| 101 | - | ## Project Structure | |
| 102 | - | ||
| 103 | - | ### Documentation (this feature) | |
| 104 | - | ``` | |
| 105 | - | specs/[###-feature]/ | |
| 106 | - | ├── plan.md # This file (/plan command output) | |
| 107 | - | ├── research.md # Phase 0 output (/plan command) | |
| 108 | - | ├── data-model.md # Phase 1 output (/plan command) | |
| 109 | - | ├── quickstart.md # Phase 1 output (/plan command) | |
| 110 | - | ├── contracts/ # Phase 1 output (/plan command) | |
| 111 | - | └── tasks.md # Phase 2 output (/tasks command - NOT created by /plan) | |
| 112 | - | ``` | |
| 113 | - | ||
| 114 | - | ### Source Code (repository root) | |
| 115 | - | ``` | |
| 116 | - | pkg/webkit/ # WebKit2GTK Go bindings + memory features | |
| 117 | - | - settings.go # Config + MemoryConfig (added) | |
| 118 | - | - webview.go # WebView public API | |
| 119 | - | - webview_cgo.go # CGO integration (memory pressure, cache model, GC) | |
| 120 | - | - memory.go # Memory manager (/proc, totals, recycling) | |
| 121 | - | - memory_example.go# Presets + validation helpers | |
| 122 | - | ||
| 123 | - | tests/ | |
| 124 | - | contract/ # Contract tests (to add) | |
| 125 | - | integration/ # Integration tests (to add) | |
| 126 | - | unit/ # Unit tests (placeholders present) | |
| 127 | - | ||
| 128 | - | internal/, services/ # Existing project modules (unchanged) | |
| 129 | - | frontend/ # Ancillary assets (unchanged) | |
| 130 | - | ``` | |
| 131 | - | ||
| 132 | - | **Structure Decision**: Single Go project — enhance `pkg/webkit` with memory features; tests live under `tests/*`. | |
| 133 | - | ||
| 134 | - | ## Phase 0: Outline & Research | |
| 135 | - | 1. **Extract unknowns from Technical Context** above: | |
| 136 | - | - For each NEEDS CLARIFICATION → research task | |
| 137 | - | - For each dependency → best practices task | |
| 138 | - | - For each integration → patterns task | |
| 139 | - | ||
| 140 | - | 2. **Generate and dispatch research agents**: | |
| 141 | - | ``` | |
| 142 | - | For each unknown in Technical Context: | |
| 143 | - | Task: "Research {unknown} for {feature context}" | |
| 144 | - | For each technology choice: | |
| 145 | - | Task: "Find best practices for {tech} in {domain}" | |
| 146 | - | ``` | |
| 147 | - | ||
| 148 | - | 3. **Consolidate findings** in `research.md` using format: | |
| 149 | - | - Decision: [what was chosen] | |
| 150 | - | - Rationale: [why chosen] | |
| 151 | - | - Alternatives considered: [what else evaluated] | |
| 152 | - | ||
| 153 | - | **Output**: research.md with all NEEDS CLARIFICATION resolved | |
| 154 | - | ||
| 155 | - | ## Phase 1: Design & Contracts | |
| 156 | - | *Prerequisites: research.md complete* | |
| 157 | - | ||
| 158 | - | 1. **Extract entities from feature spec** → `data-model.md`: | |
| 159 | - | - Entity name, fields, relationships | |
| 160 | - | - Validation rules from requirements | |
| 161 | - | - State transitions if applicable | |
| 162 | - | ||
| 163 | - | 2. **Generate API contracts** from functional requirements: | |
| 164 | - | - For each user action → endpoint | |
| 165 | - | - Use standard REST/GraphQL patterns | |
| 166 | - | - Output OpenAPI/GraphQL schema to `/contracts/` | |
| 167 | - | ||
| 168 | - | 3. **Generate contract tests** from contracts: | |
| 169 | - | - One test file per endpoint | |
| 170 | - | - Assert request/response schemas | |
| 171 | - | - Tests must fail (no implementation yet) | |
| 172 | - | ||
| 173 | - | 4. **Extract test scenarios** from user stories: | |
| 174 | - | - Each story → integration test scenario | |
| 175 | - | - Quickstart test = story validation steps | |
| 176 | - | ||
| 177 | - | 5. **Update agent file incrementally** (O(1) operation): | |
| 178 | - | - Run `/scripts/update-agent-context.sh [claude|gemini|copilot]` for your AI assistant | |
| 179 | - | - If exists: Add only NEW tech from current plan | |
| 180 | - | - Preserve manual additions between markers | |
| 181 | - | - Update recent changes (keep last 3) | |
| 182 | - | - Keep under 150 lines for token efficiency | |
| 183 | - | - Output to repository root | |
| 184 | - | ||
| 185 | - | **Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file | |
| 186 | - | ||
| 187 | - | ## Phase 2: Task Planning Approach | |
| 188 | - | *This section describes what the /tasks command will do - DO NOT execute during /plan* | |
| 189 | - | ||
| 190 | - | **Task Generation Strategy**: | |
| 191 | - | - Load `/templates/tasks-template.md` as base | |
| 192 | - | - Generate tasks from Phase 1 design docs (contracts, data model, quickstart) | |
| 193 | - | - Contract tests from webkit_memory_api.go interfaces (5-6 tasks) | |
| 194 | - | - Entity implementation tasks from data-model.md (4-5 tasks) | |
| 195 | - | - Integration tests from quickstart.md scenarios (8-10 tasks) | |
| 196 | - | - Memory optimization implementation tasks (6-8 tasks) | |
| 197 | - | ||
| 198 | - | **Specific Task Categories**: | |
| 199 | - | 1. **Contract Tests** [P]: WebKitMemoryAPI, MemoryConfigAPI, MemoryStatsAPI, WebViewLifecycleAPI | |
| 200 | - | 2. **Data Model** [P]: MemoryConfig validation, MemoryStats tracking, ProcessMemoryInfo parsing | |
| 201 | - | 3. **WebKit Integration**: Memory pressure settings, cache model configuration, GC triggers | |
| 202 | - | 4. **Memory Monitoring**: Process memory tracking, statistics collection, recycling logic | |
| 203 | - | 5. **Configuration**: Preset management, validation rules, settings persistence | |
| 204 | - | 6. **Integration Tests**: Memory reduction validation, stability testing, performance benchmarks | |
| 205 | - | ||
| 206 | - | **Ordering Strategy**: | |
| 207 | - | - TDD order: Contract tests → Integration tests → Implementation → Unit tests | |
| 208 | - | - Dependencies: MemoryConfig → WebKit integration → Memory monitoring → Statistics | |
| 209 | - | - Parallel tasks [P]: Independent contract tests, separate entity implementations | |
| 210 | - | - Sequential tasks: WebKit integration depends on configuration, monitoring depends on integration | |
| 211 | - | ||
| 212 | - | **Estimated Output**: 22-28 numbered, ordered tasks in tasks.md | |
| 213 | - | ||
| 214 | - | **IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan | |
| 215 | - | ||
| 216 | - | ## Gaps & Next Steps | |
| 217 | - | - Tests: Add contract tests for memory APIs and integration tests to verify 40–60% reduction and stability. | |
| 218 | - | - CLI/Config wiring: Expose flags/env for presets and limits; persist user choices. | |
| 219 | - | - Safeguards: Handle absence of memory APIs at runtime; version-checks where needed. | |
| 220 | - | - Observability: Ensure structured logs; optionally add an API to fetch `MemoryStats`. | |
| 221 | - | - CGO hygiene: Audit ownership/unref and goroutine shutdown paths; finalizeizers as needed. | |
| 222 | - | - Benchmarks: Script baseline vs optimized memory and performance impact. | |
| 223 | - | - Docs: Quickstart verification steps are present; add examples for presets and flags. | |
| 224 | - | ||
| 225 | - | ## Phase 3+: Future Implementation | |
| 226 | - | *These phases are beyond the scope of the /plan command* | |
| 227 | - | ||
| 228 | - | **Phase 3**: Task execution (/tasks command creates tasks.md) | |
| 229 | - | **Phase 4**: Implementation (execute tasks.md following constitutional principles) | |
| 230 | - | **Phase 5**: Validation (run tests, execute quickstart.md, performance validation) | |
| 231 | - | ||
| 232 | - | ## Complexity Tracking | |
| 233 | - | *Fill ONLY if Constitution Check has violations that must be justified* | |
| 234 | - | ||
| 235 | - | | Violation | Why Needed | Simpler Alternative Rejected Because | | |
| 236 | - | |-----------|------------|-------------------------------------| | |
| 237 | - | | [e.g., 4th project] | [current need] | [why 3 projects insufficient] | | |
| 238 | - | | [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] | | |
| 239 | - | ||
| 240 | - | ||
| 241 | - | ## Progress Tracking | |
| 242 | - | *This checklist is updated during execution flow* | |
| 243 | - | ||
| 244 | - | **Phase Status**: | |
| 245 | - | - [x] Phase 0: Research complete (/plan command) | |
| 246 | - | - [x] Phase 1: Design complete (/plan command) | |
| 247 | - | - [x] Phase 2: Task planning complete (/plan command - describe approach only) | |
| 248 | - | - [x] Phase 3: Tasks generated (tasks.md present) | |
| 249 | - | - [ ] Phase 4: Implementation complete | |
| 250 | - | - [ ] Phase 5: Validation passed | |
| 251 | - | ||
| 252 | - | **Gate Status**: | |
| 253 | - | - [x] Initial Constitution Check: PASS | |
| 254 | - | - [x] Post-Design Constitution Check: PASS | |
| 255 | - | - [x] All NEEDS CLARIFICATION resolved | |
| 256 | - | - [ ] Complexity deviations documented | |
| 257 | - | ||
| 258 | - | --- | |
| 259 | - | *Based on Constitution v2.1.1 - See `/memory/constitution.md`* | |
D specs/005-webkit-memory-optimization/quickstart.md +0 -228
| @@ -1,228 +0,0 @@ | |||
| 1 | - | # Quickstart: WebKit Memory Optimization | |
| 2 | - | ||
| 3 | - | **Feature**: 005-webkit-memory-optimization | |
| 4 | - | **Purpose**: Validate that WebKit memory optimization reduces memory usage by 40-60% while maintaining browser functionality | |
| 5 | - | **Estimated Time**: 15 minutes | |
| 6 | - | ||
| 7 | - | ## Prerequisites | |
| 8 | - | - dumb-browser built with webkit_cgo tags | |
| 9 | - | - WebKit2GTK 6.0+ installed | |
| 10 | - | - Linux system with /proc filesystem | |
| 11 | - | - At least 2GB available RAM for testing | |
| 12 | - | ||
| 13 | - | ## Quick Validation Test | |
| 14 | - | ||
| 15 | - | ### Step 1: Baseline Memory Measurement | |
| 16 | - | ```bash | |
| 17 | - | # Start browser with default settings | |
| 18 | - | ./dumber --url=https://example.com | |
| 19 | - | ||
| 20 | - | # In another terminal, measure baseline memory | |
| 21 | - | ps aux | grep dumber | grep -v grep | |
| 22 | - | # Note the RSS memory usage (column 6) - should be ~400MB | |
| 23 | - | ``` | |
| 24 | - | ||
| 25 | - | ### Step 2: Enable Memory Optimization | |
| 26 | - | ```bash | |
| 27 | - | # Stop the browser and restart with memory optimization | |
| 28 | - | ./dumber --memory-limit=256 --cache-model=document_viewer --url=https://example.com | |
| 29 | - | ||
| 30 | - | # Measure optimized memory usage | |
| 31 | - | ps aux | grep dumber | grep -v grep | |
| 32 | - | # Note the RSS memory usage - should be 150-250MB (40-60% reduction) | |
| 33 | - | ``` | |
| 34 | - | ||
| 35 | - | ### Step 3: Test Browser Functionality | |
| 36 | - | Navigate to several websites to ensure functionality is preserved: | |
| 37 | - | ```bash | |
| 38 | - | # Test different website types | |
| 39 | - | https://example.com # Simple static site | |
| 40 | - | https://news.ycombinator.com # Content-heavy site | |
| 41 | - | https://github.com # Interactive web app | |
| 42 | - | ``` | |
| 43 | - | ||
| 44 | - | **Expected**: All sites should load correctly with no functionality loss | |
| 45 | - | ||
| 46 | - | ### Step 4: Test Memory Monitoring | |
| 47 | - | ```bash | |
| 48 | - | # Enable detailed memory monitoring | |
| 49 | - | ./dumber --memory-monitoring=true --url=https://example.com | |
| 50 | - | ||
| 51 | - | # Check logs for memory events | |
| 52 | - | tail -f ~/.config/dumber/logs/memory.log | |
| 53 | - | ``` | |
| 54 | - | ||
| 55 | - | **Expected**: Log entries showing memory usage, GC events, and optimization activities | |
| 56 | - | ||
| 57 | - | ### Step 5: Test Memory Pressure Response | |
| 58 | - | ```bash | |
| 59 | - | # Simulate high memory usage by opening many tabs or heavy websites | |
| 60 | - | # Browser should automatically trigger cleanup when approaching limits | |
| 61 | - | ||
| 62 | - | # Monitor memory stats via API endpoint (if implemented) | |
| 63 | - | curl http://localhost:8080/api/memory/stats | |
| 64 | - | ``` | |
| 65 | - | ||
| 66 | - | **Expected**: Memory usage should stabilize, cleanup events should be logged | |
| 67 | - | ||
| 68 | - | ## Integration Test Scenarios | |
| 69 | - | ||
| 70 | - | ### Scenario 1: Memory-Optimized Configuration | |
| 71 | - | **Given** browser started with memory-optimized preset | |
| 72 | - | **When** I navigate to a typical website | |
| 73 | - | **Then** memory usage should be ≤250MB | |
| 74 | - | ||
| 75 | - | ```bash | |
| 76 | - | # Test memory-optimized preset | |
| 77 | - | ./dumber --preset=memory-optimized --url=https://example.com | |
| 78 | - | ps aux | grep dumber | awk '{print $6}' # Should be ≤256MB | |
| 79 | - | ``` | |
| 80 | - | ||
| 81 | - | ### Scenario 2: Process Recycling | |
| 82 | - | **Given** browser with recycling threshold set to 10 pages | |
| 83 | - | **When** I navigate to 15 different pages | |
| 84 | - | **Then** browser should recommend process recycling | |
| 85 | - | ||
| 86 | - | ```bash | |
| 87 | - | # Test process recycling | |
| 88 | - | ./dumber --recycle-threshold=10 --memory-monitoring=true | |
| 89 | - | # Navigate to 15 different URLs | |
| 90 | - | # Check logs for recycling recommendation | |
| 91 | - | ``` | |
| 92 | - | ||
| 93 | - | ### Scenario 3: Memory Stability | |
| 94 | - | **Given** browser with memory optimization enabled | |
| 95 | - | **When** I browse 50 different web pages | |
| 96 | - | **Then** memory usage should remain stable (no significant growth) | |
| 97 | - | ||
| 98 | - | ```bash | |
| 99 | - | # Test memory stability over time | |
| 100 | - | for i in {1..50}; do | |
| 101 | - | echo "Loading page $i" | |
| 102 | - | # Navigate to different pages | |
| 103 | - | sleep 2 | |
| 104 | - | ps aux | grep dumber | awk '{print $6}' >> memory_usage.log | |
| 105 | - | done | |
| 106 | - | # Analyze memory_usage.log for growth trends | |
| 107 | - | ``` | |
| 108 | - | ||
| 109 | - | ## Acceptance Criteria Validation | |
| 110 | - | ||
| 111 | - | ### ✅ FR-001: Memory Usage Reduction | |
| 112 | - | - [ ] Baseline measurement: ~400MB | |
| 113 | - | - [ ] Optimized measurement: 150-250MB | |
| 114 | - | - [ ] Reduction percentage: 40-60% | |
| 115 | - | ||
| 116 | - | ### ✅ FR-002: Configurable Memory Limits | |
| 117 | - | - [ ] Memory limit configuration working | |
| 118 | - | - [ ] Different presets produce different memory usage | |
| 119 | - | - [ ] Custom thresholds respected | |
| 120 | - | ||
| 121 | - | ### ✅ FR-003: Optimization Presets | |
| 122 | - | - [ ] Memory-optimized preset: lowest memory usage | |
| 123 | - | - [ ] Balanced preset: moderate memory usage | |
| 124 | - | - [ ] Performance preset: highest memory usage | |
| 125 | - | ||
| 126 | - | ### ✅ FR-004: Automatic Memory Cleanup | |
| 127 | - | - [ ] Memory pressure triggers cleanup | |
| 128 | - | - [ ] Cleanup completes without crashing | |
| 129 | - | - [ ] Memory usage decreases after cleanup | |
| 130 | - | ||
| 131 | - | ### ✅ FR-005: Memory Statistics | |
| 132 | - | - [ ] Memory stats API accessible | |
| 133 | - | - [ ] Statistics updated regularly | |
| 134 | - | - [ ] Historical data tracked | |
| 135 | - | ||
| 136 | - | ### ✅ FR-006: Browser Stability | |
| 137 | - | - [ ] No crashes during optimization | |
| 138 | - | - [ ] All websites load correctly | |
| 139 | - | - [ ] Navigation remains smooth | |
| 140 | - | ||
| 141 | - | ### ✅ FR-007: Essential Functionality Preserved | |
| 142 | - | - [ ] Page navigation works | |
| 143 | - | - [ ] JavaScript execution works | |
| 144 | - | - [ ] Form submission works | |
| 145 | - | - [ ] Media playback works (if applicable) | |
| 146 | - | ||
| 147 | - | ### ✅ FR-008: Manual Memory Cleanup | |
| 148 | - | - [ ] Manual cleanup trigger available | |
| 149 | - | - [ ] Cleanup executes successfully | |
| 150 | - | - [ ] Memory usage decreases after manual trigger | |
| 151 | - | ||
| 152 | - | ### ✅ FR-009: Process Recycling | |
| 153 | - | - [ ] Page load counting accurate | |
| 154 | - | - [ ] Recycling recommendations logged | |
| 155 | - | - [ ] New process has reset counters | |
| 156 | - | ||
| 157 | - | ### ✅ FR-010: Memory Event Logging | |
| 158 | - | - [ ] Memory optimization events logged | |
| 159 | - | - [ ] Log format is structured and readable | |
| 160 | - | - [ ] Log verbosity controllable | |
| 161 | - | ||
| 162 | - | ## Performance Validation | |
| 163 | - | ||
| 164 | - | ### Memory Usage Benchmarks | |
| 165 | - | ```bash | |
| 166 | - | # Run benchmark script to measure memory over time | |
| 167 | - | ./scripts/memory-benchmark.sh | |
| 168 | - | ||
| 169 | - | Expected results: | |
| 170 | - | - Startup memory: <100MB | |
| 171 | - | - Single page memory: 150-250MB (optimized) vs 350-450MB (default) | |
| 172 | - | - 10 page memory: <300MB (optimized) vs >500MB (default) | |
| 173 | - | - Memory stability: <10% growth over 50 page loads | |
| 174 | - | ``` | |
| 175 | - | ||
| 176 | - | ### Performance Impact Assessment | |
| 177 | - | ```bash | |
| 178 | - | # Measure page load times with/without optimization | |
| 179 | - | ./scripts/performance-benchmark.sh | |
| 180 | - | ||
| 181 | - | Expected results: | |
| 182 | - | - Page load time increase: <20% | |
| 183 | - | - JavaScript performance impact: <15% | |
| 184 | - | - Navigation responsiveness: maintained | |
| 185 | - | ``` | |
| 186 | - | ||
| 187 | - | ## Troubleshooting | |
| 188 | - | ||
| 189 | - | ### Common Issues | |
| 190 | - | ||
| 191 | - | **Memory optimization not working**: | |
| 192 | - | - Check WebKit2GTK version (requires 6.0+) | |
| 193 | - | - Verify webkit_cgo build tags enabled | |
| 194 | - | - Check configuration values in logs | |
| 195 | - | ||
| 196 | - | **Browser crashes with memory limits**: | |
| 197 | - | - Increase memory limit (try 512MB) | |
| 198 | - | - Disable kill threshold (set to 0) | |
| 199 | - | - Check for website-specific memory requirements | |
| 200 | - | ||
| 201 | - | **Memory monitoring not working**: | |
| 202 | - | - Verify /proc filesystem accessible | |
| 203 | - | - Check process permissions | |
| 204 | - | - Enable debug logging | |
| 205 | - | ||
| 206 | - | ### Validation Commands | |
| 207 | - | ```bash | |
| 208 | - | # Check WebKit version | |
| 209 | - | pkg-config --modversion webkitgtk-6.0 | |
| 210 | - | ||
| 211 | - | # Verify build configuration | |
| 212 | - | ./dumber --version | grep webkit_cgo | |
| 213 | - | ||
| 214 | - | # Test memory monitoring | |
| 215 | - | ./dumber --memory-monitoring=true --verbose | |
| 216 | - | ``` | |
| 217 | - | ||
| 218 | - | ## Success Criteria | |
| 219 | - | - [ ] Memory usage reduced by 40-60% compared to baseline | |
| 220 | - | - [ ] All browser functionality preserved | |
| 221 | - | - [ ] Memory monitoring and statistics working | |
| 222 | - | - [ ] Process recycling recommendations functional | |
| 223 | - | - [ ] No stability regressions | |
| 224 | - | - [ ] Configuration presets working correctly | |
| 225 | - | - [ ] Performance impact within acceptable limits (<20%) | |
| 226 | - | ||
| 227 | - | **Expected Completion Time**: 15-30 minutes depending on thorough testing | |
| 228 | - | **Pass Criteria**: All acceptance criteria validated, no critical functionality broken⏎̸ | |
D specs/005-webkit-memory-optimization/research.md +0 -142
| @@ -1,142 +0,0 @@ | |||
| 1 | - | # Research: WebKit Memory Optimization | |
| 2 | - | ||
| 3 | - | **Feature**: 005-webkit-memory-optimization | |
| 4 | - | **Phase**: 0 - Research & Technical Decisions | |
| 5 | - | **Date**: 2025-01-10 | |
| 6 | - | ||
| 7 | - | ## Technical Decisions Made | |
| 8 | - | ||
| 9 | - | ### WebKit Memory Pressure API Selection | |
| 10 | - | **Decision**: Use WebKitMemoryPressureSettings introduced in WebKit2GTK 6.0 | |
| 11 | - | **Rationale**: | |
| 12 | - | - Provides granular control over memory limits and cleanup thresholds | |
| 13 | - | - Native WebKit memory management rather than external process monitoring | |
| 14 | - | - Integrates with WebKit's internal memory pressure signals | |
| 15 | - | - Available in WebKit2GTK 6.0+ (already required by project) | |
| 16 | - | ||
| 17 | - | **Alternatives considered**: | |
| 18 | - | - Manual process monitoring via /proc filesystem: Less integrated, more overhead | |
| 19 | - | - System-level memory pressure (systemd, kernel): Too coarse-grained for per-WebView control | |
| 20 | - | - JavaScript-only GC triggers: Insufficient for WebKit native memory (images, CSS, DOM) | |
| 21 | - | ||
| 22 | - | ### Cache Model Optimization Strategy | |
| 23 | - | **Decision**: Use WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER as memory-optimized default | |
| 24 | - | **Rationale**: | |
| 25 | - | - Minimal memory caching strategy designed for document viewing | |
| 26 | - | - 40-60% less memory usage than WEBKIT_CACHE_MODEL_WEB_BROWSER | |
| 27 | - | - Still maintains reasonable performance for typical browsing | |
| 28 | - | - Configurable - users can choose more performance-oriented models | |
| 29 | - | ||
| 30 | - | **Alternatives considered**: | |
| 31 | - | - Custom cache implementation: Too complex, reinvents WebKit internals | |
| 32 | - | - Disable all caching: Would break many websites and hurt performance significantly | |
| 33 | - | - Dynamic cache model switching: Added complexity without clear benefits | |
| 34 | - | ||
| 35 | - | ### Process Recycling Implementation | |
| 36 | - | **Decision**: Track page load count per WebView, recommend recycling at configurable threshold | |
| 37 | - | **Rationale**: | |
| 38 | - | - WebKit processes accumulate memory over time due to fragmentation | |
| 39 | - | - Simple counter-based approach is reliable and predictable | |
| 40 | - | - User/application controls recycling policy, not automatic termination | |
| 41 | - | - Preserves user experience while managing long-term memory growth | |
| 42 | - | ||
| 43 | - | **Alternatives considered**: | |
| 44 | - | - Time-based recycling: Unpredictable memory impact, could interrupt user workflows | |
| 45 | - | - Memory-threshold recycling: More complex, could lead to recycling loops | |
| 46 | - | - Automatic process termination: Too aggressive, would lose user state | |
| 47 | - | ||
| 48 | - | ### Memory Monitoring Architecture | |
| 49 | - | **Decision**: Hybrid approach using /proc filesystem + WebKit memory pressure callbacks | |
| 50 | - | **Rationale**: | |
| 51 | - | - /proc provides detailed RSS/VmSize metrics for external monitoring tools | |
| 52 | - | - WebKit callbacks provide internal memory pressure events | |
| 53 | - | - Both together give complete picture for debugging and optimization | |
| 54 | - | - Enables both real-time monitoring and historical tracking | |
| 55 | - | ||
| 56 | - | **Alternatives considered**: | |
| 57 | - | - WebKit-only monitoring: Limited visibility into actual system memory usage | |
| 58 | - | - /proc-only monitoring: Misses WebKit internal memory pressure states | |
| 59 | - | - External monitoring tools: Adds dependencies, complicates deployment | |
| 60 | - | ||
| 61 | - | ### Configuration Preset Strategy | |
| 62 | - | **Decision**: Provide three preset configurations (memory-optimized, balanced, performance) | |
| 63 | - | **Rationale**: | |
| 64 | - | - Covers main use cases: low-memory devices, general use, high-performance needs | |
| 65 | - | - Simple choice for users, comprehensive under the hood | |
| 66 | - | - Provides sensible defaults while allowing customization | |
| 67 | - | - Aligns with constitutional simplicity requirements | |
| 68 | - | ||
| 69 | - | **Alternatives considered**: | |
| 70 | - | - Single configuration: Too rigid, doesn't accommodate different hardware/needs | |
| 71 | - | - Extensive customization UI: Too complex, violates constitutional simplicity | |
| 72 | - | - Auto-detection: Unpredictable, users prefer explicit control | |
| 73 | - | ||
| 74 | - | ## Implementation Technologies Confirmed | |
| 75 | - | ||
| 76 | - | ### Core Technologies | |
| 77 | - | - **WebKit2GTK 6.0**: Memory pressure settings, cache model control, JavaScript GC triggers | |
| 78 | - | - **GTK4**: Event handling, settings management (already in use) | |
| 79 | - | - **Go 1.25.1 + CGO**: C API bindings for WebKit memory features | |
| 80 | - | - **GLib/GObject**: Memory management, signal handling for WebKit callbacks | |
| 81 | - | ||
| 82 | - | ### Testing Technologies | |
| 83 | - | - **Go testing**: Unit tests for configuration validation, memory calculations | |
| 84 | - | - **Integration testing**: Real WebKit processes, actual memory measurement | |
| 85 | - | - **Contract testing**: WebKit C API contract verification | |
| 86 | - | - **Performance testing**: Memory usage benchmarking, garbage collection impact | |
| 87 | - | ||
| 88 | - | ### Monitoring Technologies | |
| 89 | - | - **/proc filesystem**: RSS, VmSize, VmPeak memory metrics | |
| 90 | - | - **WebKit memory pressure callbacks**: Internal memory state changes | |
| 91 | - | - **Go log package**: Structured logging for memory events | |
| 92 | - | - **Time-based metrics**: GC frequency, process lifecycle tracking | |
| 93 | - | ||
| 94 | - | ## Best Practices Research | |
| 95 | - | ||
| 96 | - | ### WebKit Memory Management Patterns | |
| 97 | - | - **Memory pressure thresholds**: Conservative (20-33%), Strict (35-50%), Kill (70-80%) | |
| 98 | - | - **Cache model hierarchy**: DocumentViewer < WebBrowser < PrimaryWebBrowser | |
| 99 | - | - **GC trigger frequency**: 30-120 second intervals optimal for background cleanup | |
| 100 | - | - **Process recycling**: 25-100 page loads typical before fragmentation impact | |
| 101 | - | ||
| 102 | - | ### CGO Memory Safety Patterns | |
| 103 | - | - **Finalizers**: Set on WebView structs to cleanup native resources | |
| 104 | - | - **Reference counting**: Proper release of WebKit objects via g_object_unref | |
| 105 | - | - **String handling**: CString/free pairs, defer cleanup patterns | |
| 106 | - | - **Callback safety**: Store Go pointers safely for C callback functions | |
| 107 | - | ||
| 108 | - | ### Performance Impact Mitigation | |
| 109 | - | - **Lazy configuration**: Apply memory settings only when explicitly requested | |
| 110 | - | - **Background operations**: GC and monitoring in separate goroutines | |
| 111 | - | - **Graceful degradation**: Fallback to defaults if memory APIs unavailable | |
| 112 | - | - **User control**: Make all optimizations opt-in to preserve existing performance | |
| 113 | - | ||
| 114 | - | ## Risk Assessment | |
| 115 | - | ||
| 116 | - | ### Low Risk | |
| 117 | - | - Configuration storage and validation (standard Go patterns) | |
| 118 | - | - Memory monitoring (/proc parsing is well-established) | |
| 119 | - | - Preset configurations (simple struct initialization) | |
| 120 | - | ||
| 121 | - | ### Medium Risk | |
| 122 | - | - WebKit memory pressure integration (newer API, potential version compatibility) | |
| 123 | - | - Process recycling coordination (timing and state management complexity) | |
| 124 | - | - CGO callback handling (requires careful pointer management) | |
| 125 | - | ||
| 126 | - | ### High Risk | |
| 127 | - | - Aggressive memory limits causing browser instability | |
| 128 | - | - Performance degradation from excessive GC or monitoring | |
| 129 | - | - Memory pressure false positives leading to unnecessary cleanup | |
| 130 | - | ||
| 131 | - | ### Mitigation Strategies | |
| 132 | - | - Comprehensive integration testing with real websites | |
| 133 | - | - Conservative default values with gradual optimization options | |
| 134 | - | - Extensive logging and monitoring to detect issues early | |
| 135 | - | - Graceful fallback when memory optimization fails | |
| 136 | - | ||
| 137 | - | ## Unknowns Resolved | |
| 138 | - | ✅ All technical unknowns from Phase 0 resolved | |
| 139 | - | ✅ WebKit2GTK 6.0 memory APIs researched and confirmed available | |
| 140 | - | ✅ CGO integration patterns established for memory management | |
| 141 | - | ✅ Testing approach defined for memory-related features | |
| 142 | - | ✅ Performance impact mitigation strategies identified⏎̸ | |
D specs/005-webkit-memory-optimization/spec.md +0 -106
| @@ -1,106 +0,0 @@ | |||
| 1 | - | # Feature Specification: WebKit Memory Optimization | |
| 2 | - | ||
| 3 | - | **Feature Branch**: `005-webkit-memory-optimization` | |
| 4 | - | **Created**: 2025-01-10 | |
| 5 | - | **Status**: Draft | |
| 6 | - | **Input**: User description: "webkit-memory-optimization" | |
| 7 | - | ||
| 8 | - | ## Execution Flow (main) | |
| 9 | - | ``` | |
| 10 | - | 1. Parse user description from Input | |
| 11 | - | → Feature: Reduce WebKit browser memory usage from ~400MB per instance | |
| 12 | - | 2. Extract key concepts from description | |
| 13 | - | → Actors: browser users, system administrators | |
| 14 | - | → Actions: browse websites with lower memory footprint | |
| 15 | - | → Data: memory usage metrics, configuration settings | |
| 16 | - | → Constraints: maintain browsing stability and reasonable performance | |
| 17 | - | 3. For each unclear aspect: | |
| 18 | - | → No major ambiguities identified | |
| 19 | - | 4. Fill User Scenarios & Testing section | |
| 20 | - | → Primary scenario: user browses multiple websites without high memory usage | |
| 21 | - | 5. Generate Functional Requirements | |
| 22 | - | → Each requirement focuses on memory reduction and monitoring capabilities | |
| 23 | - | 6. Identify Key Entities | |
| 24 | - | → Memory configurations, usage statistics, optimization settings | |
| 25 | - | 7. Run Review Checklist | |
| 26 | - | → No [NEEDS CLARIFICATION] markers present | |
| 27 | - | → Implementation details excluded from spec | |
| 28 | - | 8. Return: SUCCESS (spec ready for planning) | |
| 29 | - | ``` | |
| 30 | - | ||
| 31 | - | --- | |
| 32 | - | ||
| 33 | - | ## ⚡ Quick Guidelines | |
| 34 | - | - ✅ Focus on WHAT users need and WHY | |
| 35 | - | - ❌ Avoid HOW to implement (no tech stack, APIs, code structure) | |
| 36 | - | - 👥 Written for business stakeholders, not developers | |
| 37 | - | ||
| 38 | - | --- | |
| 39 | - | ||
| 40 | - | ## User Scenarios & Testing *(mandatory)* | |
| 41 | - | ||
| 42 | - | ### Primary User Story | |
| 43 | - | As a browser user, I want the browser to consume significantly less memory (40-60% reduction from current ~400MB per website) so that I can keep more browser instances open on my system without experiencing performance degradation or running out of memory. | |
| 44 | - | ||
| 45 | - | ### Acceptance Scenarios | |
| 46 | - | 1. **Given** a browser instance with default settings, **When** I navigate to a typical website, **Then** the browser should consume no more than 250MB of memory | |
| 47 | - | 2. **Given** I have browsed to 50 different web pages, **When** I check memory usage, **Then** memory consumption should remain stable and not exceed reasonable limits due to memory leaks | |
| 48 | - | 3. **Given** memory optimization is enabled, **When** the browser approaches memory limits, **Then** it should automatically clean up memory and maintain responsive performance | |
| 49 | - | 4. **Given** I configure memory optimization settings, **When** I restart the browser, **Then** my memory preferences should be preserved and applied | |
| 50 | - | ||
| 51 | - | ### Edge Cases | |
| 52 | - | - What happens when memory pressure is extremely high (system running out of RAM)? | |
| 53 | - | - How does the system handle memory optimization on low-memory devices (<4GB RAM)? | |
| 54 | - | - What occurs when a single webpage requires more memory than the configured limit? | |
| 55 | - | ||
| 56 | - | ## Requirements *(mandatory)* | |
| 57 | - | ||
| 58 | - | ### Functional Requirements | |
| 59 | - | - **FR-001**: System MUST reduce per-browser-instance memory usage by 40-60% compared to current baseline (~400MB to 150-250MB) | |
| 60 | - | - **FR-002**: System MUST provide configurable memory limits and thresholds for different usage scenarios | |
| 61 | - | - **FR-003**: Users MUST be able to choose between memory-optimized, balanced, and performance-optimized configurations | |
| 62 | - | - **FR-004**: System MUST automatically trigger memory cleanup when approaching configured memory limits | |
| 63 | - | - **FR-005**: System MUST monitor and report memory usage statistics for transparency | |
| 64 | - | - **FR-006**: System MUST maintain browser stability and prevent crashes during memory optimization | |
| 65 | - | - **FR-007**: System MUST preserve essential browsing functionality (navigation, page rendering, basic JavaScript support) | |
| 66 | - | - **FR-008**: Users MUST be able to manually trigger memory cleanup operations | |
| 67 | - | - **FR-009**: System MUST support process recycling to prevent long-term memory accumulation | |
| 68 | - | - **FR-010**: System MUST log memory optimization events for debugging and monitoring purposes | |
| 69 | - | ||
| 70 | - | ### Key Entities *(include if feature involves data)* | |
| 71 | - | - **Memory Configuration**: Settings that control memory optimization behavior, including memory limits, cleanup thresholds, caching policies, and garbage collection intervals | |
| 72 | - | - **Memory Statistics**: Real-time and historical data about browser memory usage, including RSS memory, virtual memory, page load counts, and cleanup events | |
| 73 | - | - **Optimization Preset**: Pre-configured sets of memory settings for different use cases (low-memory devices, balanced performance, high-performance scenarios) | |
| 74 | - | ||
| 75 | - | --- | |
| 76 | - | ||
| 77 | - | ## Review & Acceptance Checklist | |
| 78 | - | *GATE: Automated checks run during main() execution* | |
| 79 | - | ||
| 80 | - | ### Content Quality | |
| 81 | - | - [x] No implementation details (languages, frameworks, APIs) | |
| 82 | - | - [x] Focused on user value and business needs | |
| 83 | - | - [x] Written for non-technical stakeholders | |
| 84 | - | - [x] All mandatory sections completed | |
| 85 | - | ||
| 86 | - | ### Requirement Completeness | |
| 87 | - | - [x] No [NEEDS CLARIFICATION] markers remain | |
| 88 | - | - [x] Requirements are testable and unambiguous | |
| 89 | - | - [x] Success criteria are measurable | |
| 90 | - | - [x] Scope is clearly bounded | |
| 91 | - | - [x] Dependencies and assumptions identified | |
| 92 | - | ||
| 93 | - | --- | |
| 94 | - | ||
| 95 | - | ## Execution Status | |
| 96 | - | *Updated by main() during processing* | |
| 97 | - | ||
| 98 | - | - [x] User description parsed | |
| 99 | - | - [x] Key concepts extracted | |
| 100 | - | - [x] Ambiguities marked | |
| 101 | - | - [x] User scenarios defined | |
| 102 | - | - [x] Requirements generated | |
| 103 | - | - [x] Entities identified | |
| 104 | - | - [x] Review checklist passed | |
| 105 | - | ||
| 106 | - | ---⏎̸ | |
D specs/005-webkit-memory-optimization/tasks.md +0 -157
| @@ -1,157 +0,0 @@ | |||
| 1 | - | # Tasks: WebKit Memory Optimization | |
| 2 | - | ||
| 3 | - | **Input**: Design documents from `/specs/005-webkit-memory-optimization/` | |
| 4 | - | **Prerequisites**: plan.md (required), research.md, data-model.md, contracts/ | |
| 5 | - | ||
| 6 | - | ## Execution Flow (main) | |
| 7 | - | ``` | |
| 8 | - | 1. Load plan.md from feature directory | |
| 9 | - | → Extract: Go 1.25.1 + CGO, WebKit2GTK 6.0, memory optimization approach | |
| 10 | - | 2. Load optional design documents: | |
| 11 | - | → data-model.md: MemoryConfig, MemoryStats, ProcessMemoryInfo, WebViewMemoryManager → model tasks | |
| 12 | - | → contracts/webkit_memory_api.go: 4 interfaces → contract test tasks | |
| 13 | - | → quickstart.md: 5 validation scenarios → integration test tasks | |
| 14 | - | 3. Generate tasks by category: | |
| 15 | - | → Setup: CGO configuration, WebKit dependencies, linting | |
| 16 | - | → Tests: contract tests, integration tests for memory reduction | |
| 17 | - | → Core: memory configuration, stats tracking, WebKit integration | |
| 18 | - | → Integration: process monitoring, GC management, recycling logic | |
| 19 | - | → Polish: unit tests, performance validation, documentation | |
| 20 | - | 4. Apply task rules: | |
| 21 | - | → Different files = mark [P] for parallel | |
| 22 | - | → WebKit integration = sequential (shared CGO context) | |
| 23 | - | → Tests before implementation (TDD) | |
| 24 | - | 5. Number tasks sequentially (T001, T002...) | |
| 25 | - | 6. Generate dependency graph | |
| 26 | - | 7. Create parallel execution examples | |
| 27 | - | 8. Validate: All contracts tested, all entities modeled, all scenarios covered | |
| 28 | - | 9. Return: SUCCESS (tasks ready for execution) | |
| 29 | - | ``` | |
| 30 | - | ||
| 31 | - | ## Format: `[ID] [P?] Description` | |
| 32 | - | - **[P]**: Can run in parallel (different files, no dependencies) | |
| 33 | - | - Include exact file paths in descriptions | |
| 34 | - | ||
| 35 | - | ## Path Conventions | |
| 36 | - | - **Single project**: `pkg/webkit/` for WebKit bindings enhancement | |
| 37 | - | - Tests in `tests/contract/`, `tests/integration/`, `tests/unit/` | |
| 38 | - | - Memory optimization files in `pkg/webkit/` package | |
| 39 | - | ||
| 40 | - | ## Phase 3.1: Setup | |
| 41 | - | - [ ] T001 Verify WebKit2GTK 6.0+ dependencies and CGO build environment | |
| 42 | - | - [ ] T002 Configure webkit_cgo build tags in existing project structure | |
| 43 | - | - [ ] T003 [P] Update linting rules for CGO memory safety patterns | |
| 44 | - | ||
| 45 | - | ## Phase 3.2: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.3 | |
| 46 | - | **CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation** | |
| 47 | - | - [ ] T004 [P] Contract test WebKitMemoryAPI in tests/contract/test_webkit_memory_api_test.go | |
| 48 | - | - [ ] T005 [P] Contract test MemoryConfigAPI in tests/contract/test_memory_config_api_test.go | |
| 49 | - | - [ ] T006 [P] Contract test MemoryStatsAPI in tests/contract/test_memory_stats_api_test.go | |
| 50 | - | - [ ] T007 [P] Contract test WebViewLifecycleAPI in tests/contract/test_webview_lifecycle_api_test.go | |
| 51 | - | - [ ] T008 [P] Integration test memory reduction scenario in tests/integration/test_memory_reduction_test.go | |
| 52 | - | - [ ] T009 [P] Integration test memory stability scenario in tests/integration/test_memory_stability_test.go | |
| 53 | - | - [ ] T010 [P] Integration test process recycling scenario in tests/integration/test_process_recycling_test.go | |
| 54 | - | - [ ] T011 [P] Integration test memory monitoring scenario in tests/integration/test_memory_monitoring_test.go | |
| 55 | - | - [ ] T012 [P] Integration test optimization presets scenario in tests/integration/test_optimization_presets_test.go | |
| 56 | - | ||
| 57 | - | ## Phase 3.3: Core Implementation (ONLY after tests are failing) | |
| 58 | - | - [ ] T013 [P] MemoryConfig struct with validation in pkg/webkit/memory_config.go | |
| 59 | - | - [ ] T014 [P] ProcessMemoryInfo struct and parsing logic in pkg/webkit/process_memory.go | |
| 60 | - | - [ ] T015 [P] Optimization preset configurations in pkg/webkit/memory_presets.go | |
| 61 | - | - [ ] T016 WebViewMemoryManager singleton in pkg/webkit/memory_manager.go | |
| 62 | - | - [ ] T017 WebKit memory pressure settings integration in pkg/webkit/webview_cgo.go | |
| 63 | - | - [ ] T018 Cache model configuration in pkg/webkit/webview_cgo.go | |
| 64 | - | - [ ] T019 JavaScript garbage collection triggers in pkg/webkit/webview_cgo.go | |
| 65 | - | - [ ] T020 Page cache and offline cache controls in pkg/webkit/webview_cgo.go | |
| 66 | - | - [ ] T021 Memory statistics tracking in pkg/webkit/webview_cgo.go | |
| 67 | - | ||
| 68 | - | ## Phase 3.4: Integration | |
| 69 | - | - [ ] T022 Process memory monitoring via /proc filesystem in pkg/webkit/memory_manager.go | |
| 70 | - | - [ ] T023 Memory pressure callback handling in pkg/webkit/webview_cgo.go | |
| 71 | - | - [ ] T024 Periodic garbage collection scheduler in pkg/webkit/webview_cgo.go | |
| 72 | - | - [ ] T025 Process recycling recommendation logic in pkg/webkit/memory_manager.go | |
| 73 | - | - [ ] T026 Memory event logging and monitoring in pkg/webkit/memory_manager.go | |
| 74 | - | ||
| 75 | - | ## Phase 3.5: Polish | |
| 76 | - | - [ ] T027 [P] Unit tests for MemoryConfig validation in tests/unit/test_memory_config_test.go | |
| 77 | - | - [ ] T028 [P] Unit tests for ProcessMemoryInfo parsing in tests/unit/test_process_memory_test.go | |
| 78 | - | - [ ] T029 [P] Unit tests for optimization presets in tests/unit/test_memory_presets_test.go | |
| 79 | - | - [ ] T030 Performance validation: 40-60% memory reduction benchmark | |
| 80 | - | - [ ] T031 [P] Update CLAUDE.md with memory optimization context | |
| 81 | - | - [ ] T032 Memory safety review for CGO pointer management | |
| 82 | - | - [ ] T033 Execute quickstart.md validation scenarios | |
| 83 | - | ||
| 84 | - | ## Dependencies | |
| 85 | - | - Setup (T001-T003) before all other tasks | |
| 86 | - | - Contract tests (T004-T007) before any implementation | |
| 87 | - | - Integration tests (T008-T012) before implementation | |
| 88 | - | - T013-T015 (data models) before T016-T021 (WebKit integration) | |
| 89 | - | - T017-T021 (WebKit changes) are sequential (shared webview_cgo.go file) | |
| 90 | - | - T022-T026 (integration features) depend on T016-T021 | |
| 91 | - | - Polish (T027-T033) after all core implementation | |
| 92 | - | ||
| 93 | - | ## Parallel Example | |
| 94 | - | ``` | |
| 95 | - | # Launch contract tests together (T004-T007): | |
| 96 | - | Task: "Contract test WebKitMemoryAPI in tests/contract/test_webkit_memory_api_test.go" | |
| 97 | - | Task: "Contract test MemoryConfigAPI in tests/contract/test_memory_config_api_test.go" | |
| 98 | - | Task: "Contract test MemoryStatsAPI in tests/contract/test_memory_stats_api_test.go" | |
| 99 | - | Task: "Contract test WebViewLifecycleAPI in tests/contract/test_webview_lifecycle_api_test.go" | |
| 100 | - | ||
| 101 | - | # Launch integration tests together (T008-T012): | |
| 102 | - | Task: "Integration test memory reduction in tests/integration/test_memory_reduction_test.go" | |
| 103 | - | Task: "Integration test memory stability in tests/integration/test_memory_stability_test.go" | |
| 104 | - | Task: "Integration test process recycling in tests/integration/test_process_recycling_test.go" | |
| 105 | - | ||
| 106 | - | # Launch data model implementations together (T013-T015): | |
| 107 | - | Task: "MemoryConfig struct with validation in pkg/webkit/memory_config.go" | |
| 108 | - | Task: "ProcessMemoryInfo struct and parsing in pkg/webkit/process_memory.go" | |
| 109 | - | Task: "Optimization preset configurations in pkg/webkit/memory_presets.go" | |
| 110 | - | ``` | |
| 111 | - | ||
| 112 | - | ## Notes | |
| 113 | - | - WebKit2GTK 6.0 memory pressure APIs are the core technical dependency | |
| 114 | - | - CGO memory safety requires careful pointer management and finalizers | |
| 115 | - | - Tests must use real WebKit processes for accurate memory measurements | |
| 116 | - | - Memory reduction target: 400MB → 150-250MB (40-60% reduction) | |
| 117 | - | - All WebKit integration changes modify shared webview_cgo.go file (sequential) | |
| 118 | - | ||
| 119 | - | ## Task Generation Rules | |
| 120 | - | *Applied during main() execution* | |
| 121 | - | ||
| 122 | - | 1. **From Contracts**: | |
| 123 | - | - WebKitMemoryAPI → T004 contract test, T017-T021 implementation | |
| 124 | - | - MemoryConfigAPI → T005 contract test, T013 implementation | |
| 125 | - | - MemoryStatsAPI → T006 contract test, T021 implementation | |
| 126 | - | - WebViewLifecycleAPI → T007 contract test, T025 implementation | |
| 127 | - | ||
| 128 | - | 2. **From Data Model**: | |
| 129 | - | - MemoryConfig entity → T013 model creation task [P] | |
| 130 | - | - ProcessMemoryInfo entity → T014 model creation task [P] | |
| 131 | - | - WebViewMemoryManager entity → T016 manager implementation | |
| 132 | - | - MemoryStats → integrated into WebView (T021) | |
| 133 | - | ||
| 134 | - | 3. **From Quickstart Scenarios**: | |
| 135 | - | - Memory reduction validation → T008 integration test [P] | |
| 136 | - | - Memory stability testing → T009 integration test [P] | |
| 137 | - | - Process recycling testing → T010 integration test [P] | |
| 138 | - | - Memory monitoring testing → T011 integration test [P] | |
| 139 | - | - Optimization presets testing → T012 integration test [P] | |
| 140 | - | ||
| 141 | - | 4. **Ordering**: | |
| 142 | - | - Setup → Contract tests → Integration tests → Models → WebKit integration → Polish | |
| 143 | - | - Data models before WebKit integration | |
| 144 | - | - WebKit integration tasks sequential due to shared file | |
| 145 | - | ||
| 146 | - | ## Validation Checklist | |
| 147 | - | *GATE: Checked by main() before returning* | |
| 148 | - | ||
| 149 | - | - [x] All contracts have corresponding tests (T004-T007) | |
| 150 | - | - [x] All entities have model tasks (T013-T016) | |
| 151 | - | - [x] All tests come before implementation (T004-T012 before T013+) | |
| 152 | - | - [x] Parallel tasks truly independent (different files, no shared dependencies) | |
| 153 | - | - [x] Each task specifies exact file path | |
| 154 | - | - [x] No task modifies same file as another [P] task (webview_cgo.go tasks are sequential) | |
| 155 | - | - [x] Memory reduction goal (40-60%) addressed in T008, T030 | |
| 156 | - | - [x] All quickstart scenarios covered (T008-T012, T033) | |
| 157 | - | - [x] CGO memory safety addressed (T032)⏎̸ | |
D templates/agent-file-template.md +0 -23
| @@ -1,23 +0,0 @@ | |||
| 1 | - | # [PROJECT NAME] Development Guidelines | |
| 2 | - | ||
| 3 | - | Auto-generated from all feature plans. Last updated: [DATE] | |
| 4 | - | ||
| 5 | - | ## Active Technologies | |
| 6 | - | [EXTRACTED FROM ALL PLAN.MD FILES] | |
| 7 | - | ||
| 8 | - | ## Project Structure | |
| 9 | - | ``` | |
| 10 | - | [ACTUAL STRUCTURE FROM PLANS] | |
| 11 | - | ``` | |
| 12 | - | ||
| 13 | - | ## Commands | |
| 14 | - | [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES] | |
| 15 | - | ||
| 16 | - | ## Code Style | |
| 17 | - | [LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE] | |
| 18 | - | ||
| 19 | - | ## Recent Changes | |
| 20 | - | [LAST 3 FEATURES AND WHAT THEY ADDED] | |
| 21 | - | ||
| 22 | - | <!-- MANUAL ADDITIONS START --> | |
| 23 | - | <!-- MANUAL ADDITIONS END -->⏎̸ | |
D templates/plan-template.md +0 -237
| @@ -1,237 +0,0 @@ | |||
| 1 | - | # Implementation Plan: [FEATURE] | |
| 2 | - | ||
| 3 | - | **Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link] | |
| 4 | - | **Input**: Feature specification from `/specs/[###-feature-name]/spec.md` | |
| 5 | - | ||
| 6 | - | ## Execution Flow (/plan command scope) | |
| 7 | - | ``` | |
| 8 | - | 1. Load feature spec from Input path | |
| 9 | - | → If not found: ERROR "No feature spec at {path}" | |
| 10 | - | 2. Fill Technical Context (scan for NEEDS CLARIFICATION) | |
| 11 | - | → Detect Project Type from context (web=frontend+backend, mobile=app+api) | |
| 12 | - | → Set Structure Decision based on project type | |
| 13 | - | 3. Evaluate Constitution Check section below | |
| 14 | - | → If violations exist: Document in Complexity Tracking | |
| 15 | - | → If no justification possible: ERROR "Simplify approach first" | |
| 16 | - | → Update Progress Tracking: Initial Constitution Check | |
| 17 | - | 4. Execute Phase 0 → research.md | |
| 18 | - | → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns" | |
| 19 | - | 5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI). | |
| 20 | - | 6. Re-evaluate Constitution Check section | |
| 21 | - | → If new violations: Refactor design, return to Phase 1 | |
| 22 | - | → Update Progress Tracking: Post-Design Constitution Check | |
| 23 | - | 7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) | |
| 24 | - | 8. STOP - Ready for /tasks command | |
| 25 | - | ``` | |
| 26 | - | ||
| 27 | - | **IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands: | |
| 28 | - | - Phase 2: /tasks command creates tasks.md | |
| 29 | - | - Phase 3-4: Implementation execution (manual or via tools) | |
| 30 | - | ||
| 31 | - | ## Summary | |
| 32 | - | [Extract from feature spec: primary requirement + technical approach from research] | |
| 33 | - | ||
| 34 | - | ## Technical Context | |
| 35 | - | **Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION] | |
| 36 | - | **Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION] | |
| 37 | - | **Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A] | |
| 38 | - | **Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION] | |
| 39 | - | **Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION] | |
| 40 | - | **Project Type**: [single/web/mobile - determines source structure] | |
| 41 | - | **Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION] | |
| 42 | - | **Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION] | |
| 43 | - | **Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION] | |
| 44 | - | ||
| 45 | - | ## Constitution Check | |
| 46 | - | *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | |
| 47 | - | ||
| 48 | - | **Simplicity**: | |
| 49 | - | - Projects: [#] (max 3 - e.g., api, cli, tests) | |
| 50 | - | - Using framework directly? (no wrapper classes) | |
| 51 | - | - Single data model? (no DTOs unless serialization differs) | |
| 52 | - | - Avoiding patterns? (no Repository/UoW without proven need) | |
| 53 | - | ||
| 54 | - | **Architecture**: | |
| 55 | - | - EVERY feature as library? (no direct app code) | |
| 56 | - | - Libraries listed: [name + purpose for each] | |
| 57 | - | - CLI per library: [commands with --help/--version/--format] | |
| 58 | - | - Library docs: llms.txt format planned? | |
| 59 | - | ||
| 60 | - | **Testing (NON-NEGOTIABLE)**: | |
| 61 | - | - RED-GREEN-Refactor cycle enforced? (test MUST fail first) | |
| 62 | - | - Git commits show tests before implementation? | |
| 63 | - | - Order: Contract→Integration→E2E→Unit strictly followed? | |
| 64 | - | - Real dependencies used? (actual DBs, not mocks) | |
| 65 | - | - Integration tests for: new libraries, contract changes, shared schemas? | |
| 66 | - | - FORBIDDEN: Implementation before test, skipping RED phase | |
| 67 | - | ||
| 68 | - | **Observability**: | |
| 69 | - | - Structured logging included? | |
| 70 | - | - Frontend logs → backend? (unified stream) | |
| 71 | - | - Error context sufficient? | |
| 72 | - | ||
| 73 | - | **Versioning**: | |
| 74 | - | - Version number assigned? (MAJOR.MINOR.BUILD) | |
| 75 | - | - BUILD increments on every change? | |
| 76 | - | - Breaking changes handled? (parallel tests, migration plan) | |
| 77 | - | ||
| 78 | - | ## Project Structure | |
| 79 | - | ||
| 80 | - | ### Documentation (this feature) | |
| 81 | - | ``` | |
| 82 | - | specs/[###-feature]/ | |
| 83 | - | ├── plan.md # This file (/plan command output) | |
| 84 | - | ├── research.md # Phase 0 output (/plan command) | |
| 85 | - | ├── data-model.md # Phase 1 output (/plan command) | |
| 86 | - | ├── quickstart.md # Phase 1 output (/plan command) | |
| 87 | - | ├── contracts/ # Phase 1 output (/plan command) | |
| 88 | - | └── tasks.md # Phase 2 output (/tasks command - NOT created by /plan) | |
| 89 | - | ``` | |
| 90 | - | ||
| 91 | - | ### Source Code (repository root) | |
| 92 | - | ``` | |
| 93 | - | # Option 1: Single project (DEFAULT) | |
| 94 | - | src/ | |
| 95 | - | ├── models/ | |
| 96 | - | ├── services/ | |
| 97 | - | ├── cli/ | |
| 98 | - | └── lib/ | |
| 99 | - | ||
| 100 | - | tests/ | |
| 101 | - | ├── contract/ | |
| 102 | - | ├── integration/ | |
| 103 | - | └── unit/ | |
| 104 | - | ||
| 105 | - | # Option 2: Web application (when "frontend" + "backend" detected) | |
| 106 | - | backend/ | |
| 107 | - | ├── src/ | |
| 108 | - | │ ├── models/ | |
| 109 | - | │ ├── services/ | |
| 110 | - | │ └── api/ | |
| 111 | - | └── tests/ | |
| 112 | - | ||
| 113 | - | frontend/ | |
| 114 | - | ├── src/ | |
| 115 | - | │ ├── components/ | |
| 116 | - | │ ├── pages/ | |
| 117 | - | │ └── services/ | |
| 118 | - | └── tests/ | |
| 119 | - | ||
| 120 | - | # Option 3: Mobile + API (when "iOS/Android" detected) | |
| 121 | - | api/ | |
| 122 | - | └── [same as backend above] | |
| 123 | - | ||
| 124 | - | ios/ or android/ | |
| 125 | - | └── [platform-specific structure] | |
| 126 | - | ``` | |
| 127 | - | ||
| 128 | - | **Structure Decision**: [DEFAULT to Option 1 unless Technical Context indicates web/mobile app] | |
| 129 | - | ||
| 130 | - | ## Phase 0: Outline & Research | |
| 131 | - | 1. **Extract unknowns from Technical Context** above: | |
| 132 | - | - For each NEEDS CLARIFICATION → research task | |
| 133 | - | - For each dependency → best practices task | |
| 134 | - | - For each integration → patterns task | |
| 135 | - | ||
| 136 | - | 2. **Generate and dispatch research agents**: | |
| 137 | - | ``` | |
| 138 | - | For each unknown in Technical Context: | |
| 139 | - | Task: "Research {unknown} for {feature context}" | |
| 140 | - | For each technology choice: | |
| 141 | - | Task: "Find best practices for {tech} in {domain}" | |
| 142 | - | ``` | |
| 143 | - | ||
| 144 | - | 3. **Consolidate findings** in `research.md` using format: | |
| 145 | - | - Decision: [what was chosen] | |
| 146 | - | - Rationale: [why chosen] | |
| 147 | - | - Alternatives considered: [what else evaluated] | |
| 148 | - | ||
| 149 | - | **Output**: research.md with all NEEDS CLARIFICATION resolved | |
| 150 | - | ||
| 151 | - | ## Phase 1: Design & Contracts | |
| 152 | - | *Prerequisites: research.md complete* | |
| 153 | - | ||
| 154 | - | 1. **Extract entities from feature spec** → `data-model.md`: | |
| 155 | - | - Entity name, fields, relationships | |
| 156 | - | - Validation rules from requirements | |
| 157 | - | - State transitions if applicable | |
| 158 | - | ||
| 159 | - | 2. **Generate API contracts** from functional requirements: | |
| 160 | - | - For each user action → endpoint | |
| 161 | - | - Use standard REST/GraphQL patterns | |
| 162 | - | - Output OpenAPI/GraphQL schema to `/contracts/` | |
| 163 | - | ||
| 164 | - | 3. **Generate contract tests** from contracts: | |
| 165 | - | - One test file per endpoint | |
| 166 | - | - Assert request/response schemas | |
| 167 | - | - Tests must fail (no implementation yet) | |
| 168 | - | ||
| 169 | - | 4. **Extract test scenarios** from user stories: | |
| 170 | - | - Each story → integration test scenario | |
| 171 | - | - Quickstart test = story validation steps | |
| 172 | - | ||
| 173 | - | 5. **Update agent file incrementally** (O(1) operation): | |
| 174 | - | - Run `/scripts/update-agent-context.sh [claude|gemini|copilot]` for your AI assistant | |
| 175 | - | - If exists: Add only NEW tech from current plan | |
| 176 | - | - Preserve manual additions between markers | |
| 177 | - | - Update recent changes (keep last 3) | |
| 178 | - | - Keep under 150 lines for token efficiency | |
| 179 | - | - Output to repository root | |
| 180 | - | ||
| 181 | - | **Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file | |
| 182 | - | ||
| 183 | - | ## Phase 2: Task Planning Approach | |
| 184 | - | *This section describes what the /tasks command will do - DO NOT execute during /plan* | |
| 185 | - | ||
| 186 | - | **Task Generation Strategy**: | |
| 187 | - | - Load `/templates/tasks-template.md` as base | |
| 188 | - | - Generate tasks from Phase 1 design docs (contracts, data model, quickstart) | |
| 189 | - | - Each contract → contract test task [P] | |
| 190 | - | - Each entity → model creation task [P] | |
| 191 | - | - Each user story → integration test task | |
| 192 | - | - Implementation tasks to make tests pass | |
| 193 | - | ||
| 194 | - | **Ordering Strategy**: | |
| 195 | - | - TDD order: Tests before implementation | |
| 196 | - | - Dependency order: Models before services before UI | |
| 197 | - | - Mark [P] for parallel execution (independent files) | |
| 198 | - | ||
| 199 | - | **Estimated Output**: 25-30 numbered, ordered tasks in tasks.md | |
| 200 | - | ||
| 201 | - | **IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan | |
| 202 | - | ||
| 203 | - | ## Phase 3+: Future Implementation | |
| 204 | - | *These phases are beyond the scope of the /plan command* | |
| 205 | - | ||
| 206 | - | **Phase 3**: Task execution (/tasks command creates tasks.md) | |
| 207 | - | **Phase 4**: Implementation (execute tasks.md following constitutional principles) | |
| 208 | - | **Phase 5**: Validation (run tests, execute quickstart.md, performance validation) | |
| 209 | - | ||
| 210 | - | ## Complexity Tracking | |
| 211 | - | *Fill ONLY if Constitution Check has violations that must be justified* | |
| 212 | - | ||
| 213 | - | | Violation | Why Needed | Simpler Alternative Rejected Because | | |
| 214 | - | |-----------|------------|-------------------------------------| | |
| 215 | - | | [e.g., 4th project] | [current need] | [why 3 projects insufficient] | | |
| 216 | - | | [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] | | |
| 217 | - | ||
| 218 | - | ||
| 219 | - | ## Progress Tracking | |
| 220 | - | *This checklist is updated during execution flow* | |
| 221 | - | ||
| 222 | - | **Phase Status**: | |
| 223 | - | - [ ] Phase 0: Research complete (/plan command) | |
| 224 | - | - [ ] Phase 1: Design complete (/plan command) | |
| 225 | - | - [ ] Phase 2: Task planning complete (/plan command - describe approach only) | |
| 226 | - | - [ ] Phase 3: Tasks generated (/tasks command) | |
| 227 | - | - [ ] Phase 4: Implementation complete | |
| 228 | - | - [ ] Phase 5: Validation passed | |
| 229 | - | ||
| 230 | - | **Gate Status**: | |
| 231 | - | - [ ] Initial Constitution Check: PASS | |
| 232 | - | - [ ] Post-Design Constitution Check: PASS | |
| 233 | - | - [ ] All NEEDS CLARIFICATION resolved | |
| 234 | - | - [ ] Complexity deviations documented | |
| 235 | - | ||
| 236 | - | --- | |
| 237 | - | *Based on Constitution v2.1.1 - See `/memory/constitution.md`*⏎̸ | |
D templates/spec-template.md +0 -116
| @@ -1,116 +0,0 @@ | |||
| 1 | - | # Feature Specification: [FEATURE NAME] | |
| 2 | - | ||
| 3 | - | **Feature Branch**: `[###-feature-name]` | |
| 4 | - | **Created**: [DATE] | |
| 5 | - | **Status**: Draft | |
| 6 | - | **Input**: User description: "$ARGUMENTS" | |
| 7 | - | ||
| 8 | - | ## Execution Flow (main) | |
| 9 | - | ``` | |
| 10 | - | 1. Parse user description from Input | |
| 11 | - | → If empty: ERROR "No feature description provided" | |
| 12 | - | 2. Extract key concepts from description | |
| 13 | - | → Identify: actors, actions, data, constraints | |
| 14 | - | 3. For each unclear aspect: | |
| 15 | - | → Mark with [NEEDS CLARIFICATION: specific question] | |
| 16 | - | 4. Fill User Scenarios & Testing section | |
| 17 | - | → If no clear user flow: ERROR "Cannot determine user scenarios" | |
| 18 | - | 5. Generate Functional Requirements | |
| 19 | - | → Each requirement must be testable | |
| 20 | - | → Mark ambiguous requirements | |
| 21 | - | 6. Identify Key Entities (if data involved) | |
| 22 | - | 7. Run Review Checklist | |
| 23 | - | → If any [NEEDS CLARIFICATION]: WARN "Spec has uncertainties" | |
| 24 | - | → If implementation details found: ERROR "Remove tech details" | |
| 25 | - | 8. Return: SUCCESS (spec ready for planning) | |
| 26 | - | ``` | |
| 27 | - | ||
| 28 | - | --- | |
| 29 | - | ||
| 30 | - | ## ⚡ Quick Guidelines | |
| 31 | - | - ✅ Focus on WHAT users need and WHY | |
| 32 | - | - ❌ Avoid HOW to implement (no tech stack, APIs, code structure) | |
| 33 | - | - 👥 Written for business stakeholders, not developers | |
| 34 | - | ||
| 35 | - | ### Section Requirements | |
| 36 | - | - **Mandatory sections**: Must be completed for every feature | |
| 37 | - | - **Optional sections**: Include only when relevant to the feature | |
| 38 | - | - When a section doesn't apply, remove it entirely (don't leave as "N/A") | |
| 39 | - | ||
| 40 | - | ### For AI Generation | |
| 41 | - | When creating this spec from a user prompt: | |
| 42 | - | 1. **Mark all ambiguities**: Use [NEEDS CLARIFICATION: specific question] for any assumption you'd need to make | |
| 43 | - | 2. **Don't guess**: If the prompt doesn't specify something (e.g., "login system" without auth method), mark it | |
| 44 | - | 3. **Think like a tester**: Every vague requirement should fail the "testable and unambiguous" checklist item | |
| 45 | - | 4. **Common underspecified areas**: | |
| 46 | - | - User types and permissions | |
| 47 | - | - Data retention/deletion policies | |
| 48 | - | - Performance targets and scale | |
| 49 | - | - Error handling behaviors | |
| 50 | - | - Integration requirements | |
| 51 | - | - Security/compliance needs | |
| 52 | - | ||
| 53 | - | --- | |
| 54 | - | ||
| 55 | - | ## User Scenarios & Testing *(mandatory)* | |
| 56 | - | ||
| 57 | - | ### Primary User Story | |
| 58 | - | [Describe the main user journey in plain language] | |
| 59 | - | ||
| 60 | - | ### Acceptance Scenarios | |
| 61 | - | 1. **Given** [initial state], **When** [action], **Then** [expected outcome] | |
| 62 | - | 2. **Given** [initial state], **When** [action], **Then** [expected outcome] | |
| 63 | - | ||
| 64 | - | ### Edge Cases | |
| 65 | - | - What happens when [boundary condition]? | |
| 66 | - | - How does system handle [error scenario]? | |
| 67 | - | ||
| 68 | - | ## Requirements *(mandatory)* | |
| 69 | - | ||
| 70 | - | ### Functional Requirements | |
| 71 | - | - **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"] | |
| 72 | - | - **FR-002**: System MUST [specific capability, e.g., "validate email addresses"] | |
| 73 | - | - **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"] | |
| 74 | - | - **FR-004**: System MUST [data requirement, e.g., "persist user preferences"] | |
| 75 | - | - **FR-005**: System MUST [behavior, e.g., "log all security events"] | |
| 76 | - | ||
| 77 | - | *Example of marking unclear requirements:* | |
| 78 | - | - **FR-006**: System MUST authenticate users via [NEEDS CLARIFICATION: auth method not specified - email/password, SSO, OAuth?] | |
| 79 | - | - **FR-007**: System MUST retain user data for [NEEDS CLARIFICATION: retention period not specified] | |
| 80 | - | ||
| 81 | - | ### Key Entities *(include if feature involves data)* | |
| 82 | - | - **[Entity 1]**: [What it represents, key attributes without implementation] | |
| 83 | - | - **[Entity 2]**: [What it represents, relationships to other entities] | |
| 84 | - | ||
| 85 | - | --- | |
| 86 | - | ||
| 87 | - | ## Review & Acceptance Checklist | |
| 88 | - | *GATE: Automated checks run during main() execution* | |
| 89 | - | ||
| 90 | - | ### Content Quality | |
| 91 | - | - [ ] No implementation details (languages, frameworks, APIs) | |
| 92 | - | - [ ] Focused on user value and business needs | |
| 93 | - | - [ ] Written for non-technical stakeholders | |
| 94 | - | - [ ] All mandatory sections completed | |
| 95 | - | ||
| 96 | - | ### Requirement Completeness | |
| 97 | - | - [ ] No [NEEDS CLARIFICATION] markers remain | |
| 98 | - | - [ ] Requirements are testable and unambiguous | |
| 99 | - | - [ ] Success criteria are measurable | |
| 100 | - | - [ ] Scope is clearly bounded | |
| 101 | - | - [ ] Dependencies and assumptions identified | |
| 102 | - | ||
| 103 | - | --- | |
| 104 | - | ||
| 105 | - | ## Execution Status | |
| 106 | - | *Updated by main() during processing* | |
| 107 | - | ||
| 108 | - | - [ ] User description parsed | |
| 109 | - | - [ ] Key concepts extracted | |
| 110 | - | - [ ] Ambiguities marked | |
| 111 | - | - [ ] User scenarios defined | |
| 112 | - | - [ ] Requirements generated | |
| 113 | - | - [ ] Entities identified | |
| 114 | - | - [ ] Review checklist passed | |
| 115 | - | ||
| 116 | - | --- | |
D templates/tasks-template.md +0 -127
| @@ -1,127 +0,0 @@ | |||
| 1 | - | # Tasks: [FEATURE NAME] | |
| 2 | - | ||
| 3 | - | **Input**: Design documents from `/specs/[###-feature-name]/` | |
| 4 | - | **Prerequisites**: plan.md (required), research.md, data-model.md, contracts/ | |
| 5 | - | ||
| 6 | - | ## Execution Flow (main) | |
| 7 | - | ``` | |
| 8 | - | 1. Load plan.md from feature directory | |
| 9 | - | → If not found: ERROR "No implementation plan found" | |
| 10 | - | → Extract: tech stack, libraries, structure | |
| 11 | - | 2. Load optional design documents: | |
| 12 | - | → data-model.md: Extract entities → model tasks | |
| 13 | - | → contracts/: Each file → contract test task | |
| 14 | - | → research.md: Extract decisions → setup tasks | |
| 15 | - | 3. Generate tasks by category: | |
| 16 | - | → Setup: project init, dependencies, linting | |
| 17 | - | → Tests: contract tests, integration tests | |
| 18 | - | → Core: models, services, CLI commands | |
| 19 | - | → Integration: DB, middleware, logging | |
| 20 | - | → Polish: unit tests, performance, docs | |
| 21 | - | 4. Apply task rules: | |
| 22 | - | → Different files = mark [P] for parallel | |
| 23 | - | → Same file = sequential (no [P]) | |
| 24 | - | → Tests before implementation (TDD) | |
| 25 | - | 5. Number tasks sequentially (T001, T002...) | |
| 26 | - | 6. Generate dependency graph | |
| 27 | - | 7. Create parallel execution examples | |
| 28 | - | 8. Validate task completeness: | |
| 29 | - | → All contracts have tests? | |
| 30 | - | → All entities have models? | |
| 31 | - | → All endpoints implemented? | |
| 32 | - | 9. Return: SUCCESS (tasks ready for execution) | |
| 33 | - | ``` | |
| 34 | - | ||
| 35 | - | ## Format: `[ID] [P?] Description` | |
| 36 | - | - **[P]**: Can run in parallel (different files, no dependencies) | |
| 37 | - | - Include exact file paths in descriptions | |
| 38 | - | ||
| 39 | - | ## Path Conventions | |
| 40 | - | - **Single project**: `src/`, `tests/` at repository root | |
| 41 | - | - **Web app**: `backend/src/`, `frontend/src/` | |
| 42 | - | - **Mobile**: `api/src/`, `ios/src/` or `android/src/` | |
| 43 | - | - Paths shown below assume single project - adjust based on plan.md structure | |
| 44 | - | ||
| 45 | - | ## Phase 3.1: Setup | |
| 46 | - | - [ ] T001 Create project structure per implementation plan | |
| 47 | - | - [ ] T002 Initialize [language] project with [framework] dependencies | |
| 48 | - | - [ ] T003 [P] Configure linting and formatting tools | |
| 49 | - | ||
| 50 | - | ## Phase 3.2: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.3 | |
| 51 | - | **CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation** | |
| 52 | - | - [ ] T004 [P] Contract test POST /api/users in tests/contract/test_users_post.py | |
| 53 | - | - [ ] T005 [P] Contract test GET /api/users/{id} in tests/contract/test_users_get.py | |
| 54 | - | - [ ] T006 [P] Integration test user registration in tests/integration/test_registration.py | |
| 55 | - | - [ ] T007 [P] Integration test auth flow in tests/integration/test_auth.py | |
| 56 | - | ||
| 57 | - | ## Phase 3.3: Core Implementation (ONLY after tests are failing) | |
| 58 | - | - [ ] T008 [P] User model in src/models/user.py | |
| 59 | - | - [ ] T009 [P] UserService CRUD in src/services/user_service.py | |
| 60 | - | - [ ] T010 [P] CLI --create-user in src/cli/user_commands.py | |
| 61 | - | - [ ] T011 POST /api/users endpoint | |
| 62 | - | - [ ] T012 GET /api/users/{id} endpoint | |
| 63 | - | - [ ] T013 Input validation | |
| 64 | - | - [ ] T014 Error handling and logging | |
| 65 | - | ||
| 66 | - | ## Phase 3.4: Integration | |
| 67 | - | - [ ] T015 Connect UserService to DB | |
| 68 | - | - [ ] T016 Auth middleware | |
| 69 | - | - [ ] T017 Request/response logging | |
| 70 | - | - [ ] T018 CORS and security headers | |
| 71 | - | ||
| 72 | - | ## Phase 3.5: Polish | |
| 73 | - | - [ ] T019 [P] Unit tests for validation in tests/unit/test_validation.py | |
| 74 | - | - [ ] T020 Performance tests (<200ms) | |
| 75 | - | - [ ] T021 [P] Update docs/api.md | |
| 76 | - | - [ ] T022 Remove duplication | |
| 77 | - | - [ ] T023 Run manual-testing.md | |
| 78 | - | ||
| 79 | - | ## Dependencies | |
| 80 | - | - Tests (T004-T007) before implementation (T008-T014) | |
| 81 | - | - T008 blocks T009, T015 | |
| 82 | - | - T016 blocks T018 | |
| 83 | - | - Implementation before polish (T019-T023) | |
| 84 | - | ||
| 85 | - | ## Parallel Example | |
| 86 | - | ``` | |
| 87 | - | # Launch T004-T007 together: | |
| 88 | - | Task: "Contract test POST /api/users in tests/contract/test_users_post.py" | |
| 89 | - | Task: "Contract test GET /api/users/{id} in tests/contract/test_users_get.py" | |
| 90 | - | Task: "Integration test registration in tests/integration/test_registration.py" | |
| 91 | - | Task: "Integration test auth in tests/integration/test_auth.py" | |
| 92 | - | ``` | |
| 93 | - | ||
| 94 | - | ## Notes | |
| 95 | - | - [P] tasks = different files, no dependencies | |
| 96 | - | - Verify tests fail before implementing | |
| 97 | - | - Commit after each task | |
| 98 | - | - Avoid: vague tasks, same file conflicts | |
| 99 | - | ||
| 100 | - | ## Task Generation Rules | |
| 101 | - | *Applied during main() execution* | |
| 102 | - | ||
| 103 | - | 1. **From Contracts**: | |
| 104 | - | - Each contract file → contract test task [P] | |
| 105 | - | - Each endpoint → implementation task | |
| 106 | - | ||
| 107 | - | 2. **From Data Model**: | |
| 108 | - | - Each entity → model creation task [P] | |
| 109 | - | - Relationships → service layer tasks | |
| 110 | - | ||
| 111 | - | 3. **From User Stories**: | |
| 112 | - | - Each story → integration test [P] | |
| 113 | - | - Quickstart scenarios → validation tasks | |
| 114 | - | ||
| 115 | - | 4. **Ordering**: | |
| 116 | - | - Setup → Tests → Models → Services → Endpoints → Polish | |
| 117 | - | - Dependencies block parallel execution | |
| 118 | - | ||
| 119 | - | ## Validation Checklist | |
| 120 | - | *GATE: Checked by main() before returning* | |
| 121 | - | ||
| 122 | - | - [ ] All contracts have corresponding tests | |
| 123 | - | - [ ] All entities have model tasks | |
| 124 | - | - [ ] All tests come before implementation | |
| 125 | - | - [ ] Parallel tasks truly independent | |
| 126 | - | - [ ] Each task specifies exact file path | |
| 127 | - | - [ ] No task modifies same file as another [P] task⏎̸ | |