diff --git a/.beads/.gitignore b/.beads/.gitignore new file mode 100644 index 0000000..df4911d --- /dev/null +++ b/.beads/.gitignore @@ -0,0 +1,73 @@ +# Dolt database (managed by Dolt, not git) +dolt/ +embeddeddolt/ + +# Runtime files +bd.sock +bd.sock.startlock +sync-state.json +last-touched +.exclusive-lock + +# Daemon runtime (lock, log, pid) +daemon.* + +# Interactions log (runtime, not versioned) +interactions.jsonl + +# Push state (runtime, per-machine) +push-state.json + +# Lock files (various runtime locks) +*.lock + +# Credential key (encryption key for federation peer auth — never commit) +.beads-credential-key + +# Local version tracking (prevents upgrade notification spam after git ops) +.local_version + +# Worktree redirect file (contains relative path to main repo's .beads/) +# Must not be committed as paths would be wrong in other clones +redirect + +# Sync state (local-only, per-machine) +# These files are machine-specific and should not be shared across clones +.sync.lock +export-state/ +export-state.json + +# Ephemeral store (SQLite - wisps/molecules, intentionally not versioned) +ephemeral.sqlite3 +ephemeral.sqlite3-journal +ephemeral.sqlite3-wal +ephemeral.sqlite3-shm + +# Dolt server management (auto-started by bd) +dolt-server.pid +dolt-server.log +dolt-server.lock +dolt-server.port +dolt-server.activity + +# Corrupt backup directories (created by bd doctor --fix recovery) +*.corrupt.backup/ + +# Backup data (auto-exported JSONL, local-only) +backup/ + +# Per-project environment file (Dolt connection config, GH#2520) +.env + +# Legacy files (from pre-Dolt versions) +*.db +*.db?* +*.db-journal +*.db-wal +*.db-shm +db.sqlite +bd.db +# NOTE: Do NOT add negation patterns here. +# They would override fork protection in .git/info/exclude. +# Config files (metadata.json, config.yaml) are tracked by git by default +# since no pattern above ignores them. diff --git a/.beads/README.md b/.beads/README.md new file mode 100644 index 0000000..dbfe363 --- /dev/null +++ b/.beads/README.md @@ -0,0 +1,81 @@ +# Beads - AI-Native Issue Tracking + +Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code. + +## What is Beads? + +Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git. + +**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads) + +## Quick Start + +### Essential Commands + +```bash +# Create new issues +bd create "Add user authentication" + +# View all issues +bd list + +# View issue details +bd show + +# Update issue status +bd update --claim +bd update --status done + +# Sync with Dolt remote +bd dolt push +``` + +### Working with Issues + +Issues in Beads are: +- **Git-native**: Stored in Dolt database with version control and branching +- **AI-friendly**: CLI-first design works perfectly with AI coding agents +- **Branch-aware**: Issues can follow your branch workflow +- **Always in sync**: Auto-syncs with your commits + +## Why Beads? + +✨ **AI-Native Design** +- Built specifically for AI-assisted development workflows +- CLI-first interface works seamlessly with AI coding agents +- No context switching to web UIs + +🚀 **Developer Focused** +- Issues live in your repo, right next to your code +- Works offline, syncs when you push +- Fast, lightweight, and stays out of your way + +🔧 **Git Integration** +- Automatic sync with git commits +- Branch-aware issue tracking +- Dolt-native three-way merge resolution + +## Get Started with Beads + +Try Beads in your own projects: + +```bash +# Install Beads +curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash + +# Initialize in your repo +bd init + +# Create your first issue +bd create "Try out Beads" +``` + +## Learn More + +- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs) +- **Quick Start Guide**: Run `bd quickstart` +- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples) + +--- + +*Beads: Issue tracking that moves at the speed of thought* ⚡ diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl new file mode 100644 index 0000000..aeaed20 --- /dev/null +++ b/.beads/beads.jsonl @@ -0,0 +1,22 @@ +{"id":"phase1-epic","type":"epic","title":"Phase 1: Foundation (Auth, Git Repos, Project Structure)","description":"Rebuild Headquarter platform from scratch starting with foundational layer: Authentik OAuth auth, git repository management with bare repos on disk, SSH key management, user profiles, and basic project structure. Provides core infrastructure for Phase 2 (tool spawning) and Phase 3 (collaboration).","status":"open","priority":0,"parent":null,"external_ref":"prd:./tasks/prd-phase1-foundation.md","dependencies":[]} +{"id":"phase1-001","type":"story","title":"US-001: Docker Infrastructure & Project Bootstrap","description":"As a developer, I want a Docker Compose setup with all required services so that I can run the platform locally.\n\n## Acceptance Criteria\n- [ ] `docker-compose.yml` with PostgreSQL, Redis, Traefik, and Authentik services\n- [ ] `apps/api/Dockerfile` with multi-stage build for FastAPI\n- [ ] `apps/web/Dockerfile` for React SPA with Vite\n- [ ] `.env.example` documenting all required environment variables\n- [ ] Health checks for all services\n- [ ] `Makefile` with common commands (`make up`, `make down`, `make logs`, `make migrate`)\n- [ ] Git repo storage directory mounted as Docker volume\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass","status":"open","priority":1,"parent":"phase1-epic","external_ref":null,"dependencies":[]} +{"id":"phase1-002","type":"story","title":"US-002: Database Models & Alembic Migrations","description":"As a developer, I want database models for users, projects, and git repos so that the data layer is consistent and versioned.\n\n## Acceptance Criteria\n- [ ] SQLAlchemy models: User, Project, GitRepository, SSHKey, UserConfig\n- [ ] Relationships: User owns Projects, Project has GitRepositories, User has SSHKeys\n- [ ] Alembic initialized with initial migration script\n- [ ] Migration command documented in Makefile\n- [ ] Database seed script for development (creates test user)\n- [ ] All models use SQLAlchemy 2.0 async style\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass","status":"open","priority":1,"parent":"phase1-epic","external_ref":null,"dependencies":[]} +{"id":"phase1-003","type":"story","title":"US-003: Authentik OAuth Authentication with httpOnly Cookies","description":"As a user, I want to log in via Authentik OAuth with secure httpOnly cookies so that my session is protected from XSS attacks.\n\n## Acceptance Criteria\n- [ ] OAuth2/OIDC flow implemented with Authentik as provider\n- [ ] Callback endpoint exchanges code for tokens and sets httpOnly, Secure, SameSite=strict cookies\n- [ ] Token refresh mechanism with refresh token rotation\n- [ ] `/auth/me` endpoint returning current authenticated user\n- [ ] `/auth/logout` endpoint clearing all auth cookies\n- [ ] JWT validation middleware protecting all API routes (except public)\n- [ ] Frontend login button redirecting to Authentik\n- [ ] Frontend handles OAuth callback and refreshes user state\n- [ ] Tests mocking Authentik OIDC endpoints\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass","status":"open","priority":1,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-002"]} +{"id":"phase1-004","type":"story","title":"US-004: User Profile Management","description":"As a user, I want to view and edit my profile so that my information is up to date.\n\n## Acceptance Criteria\n- [ ] `GET /users/me` endpoint returning current user profile\n- [ ] `PATCH /users/me` endpoint for updating profile fields (name, email)\n- [ ] Frontend profile page displaying user info\n- [ ] Frontend profile edit form with validation\n- [ ] Avatar upload support (stored locally, not external service)\n- [ ] Tests for profile CRUD operations\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass\n- `npm run typecheck` must pass\n- `npm run lint` must pass","status":"open","priority":2,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-003"]} +{"id":"phase1-005","type":"story","title":"US-005: Git Repository Creation & Cloning","description":"As a user, I want to create new git repositories or clone existing ones so that I can start working on projects.\n\n## Acceptance Criteria\n- [ ] `POST /repos` endpoint to create a new bare git repository\n- [ ] `POST /repos/clone` endpoint to clone an existing repo (bare mirror)\n- [ ] Repositories stored as bare repos on disk in structured path (`/data/repos/{user_id}/{project_id}/{repo_name}.git`)\n- [ ] `GET /repos` listing all user repositories\n- [ ] `GET /repos/{id}` returning repo details (name, path, created_at, last_push)\n- [ ] `DELETE /repos/{id}` removing repo from disk and database\n- [ ] Validation preventing duplicate repo names per project\n- [ ] Frontend repo list page\n- [ ] Frontend forms for create and clone operations\n- [ ] Tests for repo lifecycle (create, clone, delete)\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass\n- `npm run typecheck` must pass\n- `npm run lint` must pass","status":"open","priority":2,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-002"]} +{"id":"phase1-006","type":"story","title":"US-006: SSH Key Management","description":"As a user, I want to generate and manage SSH keys for git operations so that I can authenticate with external git providers.\n\n## Acceptance Criteria\n- [ ] `POST /ssh-keys` endpoint generating Ed25519 key pair\n- [ ] `GET /ssh-keys` listing user's SSH keys\n- [ ] `DELETE /ssh-keys/{id}` removing a key\n- [ ] Public key displayed in OpenSSH format\n- [ ] Private key encrypted at rest (using Fernet with app secret)\n- [ ] SSH keys associated with User (global) or Project (project-specific)\n- [ ] Frontend SSH key management page\n- [ ] Frontend key generation with one-click copy of public key\n- [ ] Tests for key generation and encryption\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass\n- `npm run typecheck` must pass\n- `npm run lint` must pass","status":"open","priority":2,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-002"]} +{"id":"phase1-007","type":"story","title":"US-007: Project Structure & Organization","description":"As a user, I want to organize repositories into projects so that I can group related work.\n\n## Acceptance Criteria\n- [ ] `POST /projects` endpoint creating a new project\n- [ ] `GET /projects` listing user's projects\n- [ ] `GET /projects/{id}` returning project with associated repos\n- [ ] `PATCH /projects/{id}` updating project name/description\n- [ ] `DELETE /projects/{id}` deleting project and all associated repos\n- [ ] Project settings page for default SSH key selection\n- [ ] Frontend project list and detail pages\n- [ ] Frontend project creation form\n- [ ] Tests for project CRUD and cascading delete\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass\n- `npm run typecheck` must pass\n- `npm run lint` must pass","status":"open","priority":2,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-002","phase1-005"]} +{"id":"phase1-008","type":"story","title":"US-008: User Configuration System","description":"As a user, I want to set global preferences so that the platform behaves according to my preferences.\n\n## Acceptance Criteria\n- [ ] `UserConfig` model with key-value storage (JSONB)\n- [ ] `GET /config` endpoint returning user configuration\n- [ ] `PATCH /config` endpoint updating configuration\n- [ ] Supported config keys: default_editor, theme, git_user_name, git_user_email\n- [ ] Frontend settings page with config form\n- [ ] Config applied on frontend (theme, default values)\n- [ ] Tests for config CRUD\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass\n- `npm run typecheck` must pass\n- `npm run lint` must pass","status":"open","priority":2,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-003"]} +{"id":"phase1-009","type":"story","title":"US-009: Frontend Foundation & Layout","description":"As a user, I want a modern React frontend with navigation so that I can access all features.\n\n## Acceptance Criteria\n- [ ] React 18+ with TypeScript and Vite\n- [ ] React Router setup with protected routes\n- [ ] Tailwind CSS for styling\n- [ ] Layout component with header, sidebar navigation, and main content area\n- [ ] Navigation links: Dashboard, Projects, Repositories, SSH Keys, Settings\n- [ ] Responsive design (mobile hamburger menu)\n- [ ] Loading states and error boundaries\n- [ ] Axios/fetch configured with credentials (cookies)\n- [ ] Basic dashboard page showing user stats (repo count, project count)\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass\n- `npm run typecheck` must pass\n- `npm run lint` must pass","status":"open","priority":2,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-003","phase1-004"]} +{"id":"phase1-010","type":"story","title":"US-010: API Documentation & Health Checks","description":"As a developer, I want API documentation and health endpoints so that I can monitor and integrate with the platform.\n\n## Acceptance Criteria\n- [ ] OpenAPI/Swagger UI at `/docs` with all endpoints documented\n- [ ] `/health` endpoint returning database and service status\n- [ ] `/health/db` endpoint for database connectivity check\n- [ ] README in `apps/api/` with setup instructions\n- [ ] Architecture Decision Record (ADR) for httpOnly cookie auth choice\n- [ ] All quality gates passing\n\n## Quality Gates\n- `pytest` must pass\n- `mypy .` must pass\n- `ruff check .` must pass","status":"open","priority":3,"parent":"phase1-epic","external_ref":null,"dependencies":["phase1-003"]} +{"id":"phase2-epic","type":"epic","title":"Phase 2: Tool Runtime (Docker Tools, Web Access, Terminal)","description":"Extend Headquarter platform with Docker-based tool runtime system. Enables launching development tools (code-server, Jupyter, opencode) from git repositories, accessing their web UIs via Traefik routes, and interacting through web-based terminals. Tools are defined via Docker Compose templates and spawned into isolated containers.","status":"open","priority":0,"parent":null,"external_ref":"prd:./tasks/prd-phase2-tool-runtime.md","dependencies":[]} +{"id":"phase2-011","type":"story","title":"US-011: Tool Type Definition System","description":"As an admin, I want to define tool types using Docker Compose templates so that new tools can be added without code changes.\n\n## Acceptance Criteria\n- [ ] Create ToolType model with fields: name, description, docker_compose_template, icon, category, default_env_vars, default_ports\n- [ ] Support template variables: {{REPO_PATH}}, {{WORKSPACE_DIR}}, {{USER_ID}}, {{PROJECT_ID}}, {{TOOL_ID}}\n- [ ] Seed database with 3 built-in tool types: code-server, jupyter-notebook, opencode\n- [ ] GET /tool-types endpoint listing all available tool types\n- [ ] GET /tool-types/{id} returning tool type details\n- [ ] Docker Compose templates validated on create/update\n- [ ] Tests for template validation and variable substitution\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass","status":"open","priority":1,"parent":"phase2-epic","external_ref":null,"dependencies":[]} +{"id":"phase2-012","type":"story","title":"US-012: Tool Instance Model & Database Schema","description":"As a developer, I want a database model for tool instances so that I can track running tools and their state.\n\n## Acceptance Criteria\n- [ ] Create ToolInstance model with fields: id, name, project_id, repo_id, tool_type_id, status, container_id, subdomain, ports, env_vars, created_at, started_at, stopped_at\n- [ ] Status enum: pending, building, running, stopped, error\n- [ ] Relationship: ToolInstance belongs to Project and GitRepository\n- [ ] Alembic migration for tool instance tables\n- [ ] ToolInstanceConfig model for per-instance config overrides\n- [ ] Tests for model relationships and status transitions\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass","status":"open","priority":1,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-011"]} +{"id":"phase2-013","type":"story","title":"US-013: Docker Compose Template Engine","description":"As a developer, I want a template engine that renders Docker Compose files with project-specific values so that tools launch with correct configuration.\n\n## Acceptance Criteria\n- [ ] Implement template rendering engine (Jinja2 or string replacement)\n- [ ] Variable substitution: {{REPO_PATH}}, {{WORKSPACE_DIR}}, {{USER_ID}}, {{PROJECT_ID}}, {{TOOL_ID}}, {{SUBDOMAIN}}\n- [ ] Support environment variable injection from project/user config\n- [ ] Support port mapping configuration (host port allocation)\n- [ ] Support volume mounts (repo code, config files, persistent data)\n- [ ] Support network attachment (Traefik network)\n- [ ] Tests for template rendering with various inputs\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass","status":"open","priority":1,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-011"]} +{"id":"phase2-014","type":"story","title":"US-014: Tool Spawning & Docker Integration","description":"As a user, I want to launch tools from my repositories so that I can start working immediately.\n\n## Acceptance Criteria\n- [ ] POST /tools endpoint to create and launch a tool instance\n- [ ] Accept parameters: name, project_id, repo_id, tool_type_id, env_vars (optional), config_overrides (optional)\n- [ ] Generate unique subdomain: {tool-name}-{tool-id}.hq.local\n- [ ] Render Docker Compose template with project values\n- [ ] Execute docker compose up -d to launch container\n- [ ] Store container_id and update status to running\n- [ ] Handle build errors and set status to error with logs\n- [ ] POST /tools/{id}/stop to stop container (docker compose stop)\n- [ ] POST /tools/{id}/start to start stopped container\n- [ ] DELETE /tools/{id} to stop and remove container + data\n- [ ] Tests mocking Docker compose commands\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass","status":"open","priority":2,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-012","phase2-013"]} +{"id":"phase2-015","type":"story","title":"US-015: Traefik Route Generation","description":"As a user, I want tools accessible via clean URLs so that I can access them without remembering ports.\n\n## Acceptance Criteria\n- [ ] Auto-generate Traefik labels on tool containers:\n - traefik.enable=true\n - traefik.http.routers.{tool_id}.rule=Host({subdomain}.hq.local)\n - traefik.http.routers.{tool_id}.entrypoints=web\n - traefik.http.services.{tool_id}.loadbalancer.server.port={port}\n- [ ] Tools join Traefik Docker network for routing\n- [ ] GET /tools/{id}/url returning accessible URL\n- [ ] Handle subdomain collisions (append random suffix if needed)\n- [ ] Support HTTPS in production (websecure entrypoint)\n- [ ] Tests for label generation and URL construction\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass","status":"open","priority":2,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-014"]} +{"id":"phase2-016","type":"story","title":"US-016: Web-Based Terminal (xterm.js)","description":"As a user, I want a terminal in my browser to interact with running tools so that I don't need SSH access.\n\n## Acceptance Criteria\n- [ ] WebSocket endpoint /ws/terminal/{tool_id} for terminal sessions\n- [ ] Use docker exec to spawn shell in running container\n- [ ] Stream stdin/stdout/stderr via WebSocket\n- [ ] Terminal resize support (COLS, ROWS)\n- [ ] Session cleanup on disconnect\n- [ ] Authentication: only tool owner can access terminal\n- [ ] Frontend terminal component using xterm.js\n- [ ] Terminal connects to WebSocket with auth token\n- [ ] Support multiple terminal sessions per tool\n- [ ] Tests for WebSocket terminal lifecycle\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass\n- npm run typecheck must pass\n- npm run lint must pass","status":"open","priority":2,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-014"]} +{"id":"phase2-017","type":"story","title":"US-017: Tool Status Monitoring & Logs","description":"As a user, I want to see if my tools are running and view their logs so that I can debug issues.\n\n## Acceptance Criteria\n- [ ] GET /tools/{id}/status returning real-time container status\n- [ ] GET /tools/{id}/logs returning recent container logs (tail 100)\n- [ ] GET /tools/{id}/logs/stream WebSocket for live log streaming\n- [ ] Frontend tool dashboard showing:\n - Status indicator (running/stopped/error)\n - Uptime counter\n - Quick actions (start/stop/restart)\n - Log viewer with auto-scroll\n- [ ] Auto-refresh status every 5 seconds\n- [ ] Tests for status checking and log retrieval\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass\n- npm run typecheck must pass\n- npm run lint must pass","status":"open","priority":2,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-014"]} +{"id":"phase2-018","type":"story","title":"US-018: Frontend Tool Management UI","description":"As a user, I want a web interface to manage my tools so that I can launch, monitor, and access them easily.\n\n## Acceptance Criteria\n- [ ] Tools page listing all user's tool instances\n- [ ] Launch Tool button opening creation form\n- [ ] Form fields: name, project (dropdown), repository (dropdown), tool type (dropdown), environment variables (key-value), config overrides\n- [ ] Tool detail page showing:\n - Status and info\n - Open button (links to tool URL)\n - Terminal button (opens web terminal)\n - Logs panel\n - Settings (env vars, restart, delete)\n- [ ] Tool cards on dashboard showing quick stats\n- [ ] Empty state when no tools exist\n- [ ] Tests for tool CRUD operations in frontend\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass\n- npm run typecheck must pass\n- npm run lint must pass","status":"open","priority":2,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-015","phase2-016","phase2-017"]} +{"id":"phase2-019","type":"story","title":"US-019: Tool Configuration & Environment Variables","description":"As a user, I want to configure tools with custom environment variables and settings so that they work for my specific needs.\n\n## Acceptance Criteria\n- [ ] Global tool config at user level (default env vars for all tools)\n- [ ] Project-level tool config (overrides global defaults)\n- [ ] Tool instance-level config (overrides project defaults)\n- [ ] PATCH /tools/{id}/config endpoint for updating config\n- [ ] Config inheritance: user defaults -> project overrides -> instance overrides\n- [ ] Frontend config editor with key-value pairs\n- [ ] Support for secret values (masked in UI, encrypted at rest)\n- [ ] Tests for config inheritance and override logic\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass\n- npm run typecheck must pass\n- npm run lint must pass","status":"open","priority":3,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-014"]} +{"id":"phase2-020","type":"story","title":"US-020: Phase 2 Integration & Documentation","description":"As a developer, I want Phase 2 fully integrated with Phase 1 and documented so that the platform is cohesive.\n\n## Acceptance Criteria\n- [ ] Tool instances linked to projects and repositories (Phase 1 models)\n- [ ] SSH keys from Phase 1 available inside tool containers (mount ~/.ssh)\n- [ ] Git user config from Phase 1 applied to tool containers\n- [ ] Update API docs with all new endpoints\n- [ ] README section for tool configuration\n- [ ] Architecture Decision Record (ADR) for Docker Compose template approach\n- [ ] All quality gates passing\n- [ ] End-to-end test: create repo -> launch code-server -> access via URL -> open terminal\n\n## Quality Gates\n- pytest must pass\n- mypy . must pass\n- ruff check . must pass\n- npm run typecheck must pass\n- npm run lint must pass","status":"open","priority":3,"parent":"phase2-epic","external_ref":null,"dependencies":["phase2-015","phase2-016","phase2-017","phase2-018","phase2-019"]} diff --git a/.beads/config.yaml b/.beads/config.yaml new file mode 100644 index 0000000..232b151 --- /dev/null +++ b/.beads/config.yaml @@ -0,0 +1,54 @@ +# Beads Configuration File +# This file configures default behavior for all bd commands in this repository +# All settings can also be set via environment variables (BD_* prefix) +# or overridden with command-line flags + +# Issue prefix for this repository (used by bd init) +# If not set, bd init will auto-detect from directory name +# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc. +# issue-prefix: "" + +# Use no-db mode: JSONL-only, no Dolt database +# When true, bd will use .beads/issues.jsonl as the source of truth +# no-db: false + +# Enable JSON output by default +# json: false + +# Feedback title formatting for mutating commands (create/update/close/dep/edit) +# 0 = hide titles, N > 0 = truncate to N characters +# output: +# title-length: 255 + +# Default actor for audit trails (overridden by BEADS_ACTOR or --actor) +# actor: "" + +# Export events (audit trail) to .beads/events.jsonl on each flush/sync +# When enabled, new events are appended incrementally using a high-water mark. +# Use 'bd export --events' to trigger manually regardless of this setting. +# events-export: false + +# Multi-repo configuration (experimental - bd-307) +# Allows hydrating from multiple repositories and routing writes to the correct database +# repos: +# primary: "." # Primary repo (where this database lives) +# additional: # Additional repos to hydrate from (read-only) +# - ~/beads-planning # Personal planning repo +# - ~/work-planning # Work planning repo + +# JSONL backup (periodic export for off-machine recovery) +# Auto-enabled when a git remote exists. Override explicitly: +# backup: +# enabled: false # Disable auto-backup entirely +# interval: 15m # Minimum time between auto-exports +# git-push: false # Disable git push (export locally only) +# git-repo: "" # Separate git repo for backups (default: project repo) + +# Integration settings (access with 'bd config get/set') +# These are stored in the database, not in this file: +# - jira.url +# - jira.project +# - linear.url +# - linear.api-key +# - github.org +# - github.repo diff --git a/.beads/hooks/post-checkout b/.beads/hooks/post-checkout new file mode 100755 index 0000000..d485872 --- /dev/null +++ b/.beads/hooks/post-checkout @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# --- BEGIN BEADS INTEGRATION v1.0.3 --- +# This section is managed by beads. Do not remove these markers. +if command -v bd >/dev/null 2>&1; then + export BD_GIT_HOOK=1 + _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} + if command -v timeout >/dev/null 2>&1; then + timeout "$_bd_timeout" bd hooks run post-checkout "$@" + _bd_exit=$? + if [ $_bd_exit -eq 124 ]; then + echo >&2 "beads: hook 'post-checkout' timed out after ${_bd_timeout}s — continuing without beads" + _bd_exit=0 + fi + else + bd hooks run post-checkout "$@" + _bd_exit=$? + fi + if [ $_bd_exit -eq 3 ]; then + echo >&2 "beads: database not initialized — skipping hook 'post-checkout'" + _bd_exit=0 + fi + if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi +fi +# --- END BEADS INTEGRATION v1.0.3 --- diff --git a/.beads/hooks/post-merge b/.beads/hooks/post-merge new file mode 100755 index 0000000..5aa3315 --- /dev/null +++ b/.beads/hooks/post-merge @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# --- BEGIN BEADS INTEGRATION v1.0.3 --- +# This section is managed by beads. Do not remove these markers. +if command -v bd >/dev/null 2>&1; then + export BD_GIT_HOOK=1 + _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} + if command -v timeout >/dev/null 2>&1; then + timeout "$_bd_timeout" bd hooks run post-merge "$@" + _bd_exit=$? + if [ $_bd_exit -eq 124 ]; then + echo >&2 "beads: hook 'post-merge' timed out after ${_bd_timeout}s — continuing without beads" + _bd_exit=0 + fi + else + bd hooks run post-merge "$@" + _bd_exit=$? + fi + if [ $_bd_exit -eq 3 ]; then + echo >&2 "beads: database not initialized — skipping hook 'post-merge'" + _bd_exit=0 + fi + if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi +fi +# --- END BEADS INTEGRATION v1.0.3 --- diff --git a/.beads/hooks/pre-commit b/.beads/hooks/pre-commit new file mode 100755 index 0000000..d7ac3d9 --- /dev/null +++ b/.beads/hooks/pre-commit @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# --- BEGIN BEADS INTEGRATION v1.0.3 --- +# This section is managed by beads. Do not remove these markers. +if command -v bd >/dev/null 2>&1; then + export BD_GIT_HOOK=1 + _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} + if command -v timeout >/dev/null 2>&1; then + timeout "$_bd_timeout" bd hooks run pre-commit "$@" + _bd_exit=$? + if [ $_bd_exit -eq 124 ]; then + echo >&2 "beads: hook 'pre-commit' timed out after ${_bd_timeout}s — continuing without beads" + _bd_exit=0 + fi + else + bd hooks run pre-commit "$@" + _bd_exit=$? + fi + if [ $_bd_exit -eq 3 ]; then + echo >&2 "beads: database not initialized — skipping hook 'pre-commit'" + _bd_exit=0 + fi + if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi +fi +# --- END BEADS INTEGRATION v1.0.3 --- diff --git a/.beads/hooks/pre-push b/.beads/hooks/pre-push new file mode 100755 index 0000000..5af9e7b --- /dev/null +++ b/.beads/hooks/pre-push @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# --- BEGIN BEADS INTEGRATION v1.0.3 --- +# This section is managed by beads. Do not remove these markers. +if command -v bd >/dev/null 2>&1; then + export BD_GIT_HOOK=1 + _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} + if command -v timeout >/dev/null 2>&1; then + timeout "$_bd_timeout" bd hooks run pre-push "$@" + _bd_exit=$? + if [ $_bd_exit -eq 124 ]; then + echo >&2 "beads: hook 'pre-push' timed out after ${_bd_timeout}s — continuing without beads" + _bd_exit=0 + fi + else + bd hooks run pre-push "$@" + _bd_exit=$? + fi + if [ $_bd_exit -eq 3 ]; then + echo >&2 "beads: database not initialized — skipping hook 'pre-push'" + _bd_exit=0 + fi + if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi +fi +# --- END BEADS INTEGRATION v1.0.3 --- diff --git a/.beads/hooks/prepare-commit-msg b/.beads/hooks/prepare-commit-msg new file mode 100755 index 0000000..f0aec3c --- /dev/null +++ b/.beads/hooks/prepare-commit-msg @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# --- BEGIN BEADS INTEGRATION v1.0.3 --- +# This section is managed by beads. Do not remove these markers. +if command -v bd >/dev/null 2>&1; then + export BD_GIT_HOOK=1 + _bd_timeout=${BEADS_HOOK_TIMEOUT:-300} + if command -v timeout >/dev/null 2>&1; then + timeout "$_bd_timeout" bd hooks run prepare-commit-msg "$@" + _bd_exit=$? + if [ $_bd_exit -eq 124 ]; then + echo >&2 "beads: hook 'prepare-commit-msg' timed out after ${_bd_timeout}s — continuing without beads" + _bd_exit=0 + fi + else + bd hooks run prepare-commit-msg "$@" + _bd_exit=$? + fi + if [ $_bd_exit -eq 3 ]; then + echo >&2 "beads: database not initialized — skipping hook 'prepare-commit-msg'" + _bd_exit=0 + fi + if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi +fi +# --- END BEADS INTEGRATION v1.0.3 --- diff --git a/.beads/metadata.json b/.beads/metadata.json new file mode 100644 index 0000000..4831125 --- /dev/null +++ b/.beads/metadata.json @@ -0,0 +1,7 @@ +{ + "database": "dolt", + "backend": "dolt", + "dolt_mode": "embedded", + "dolt_database": "headquarter", + "project_id": "d9aa6d40-ce59-4c2c-8cea-f33879137a56" +} \ No newline at end of file diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..963a538 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,26 @@ +{ + "hooks": { + "PreCompact": [ + { + "hooks": [ + { + "command": "bd prime", + "type": "command" + } + ], + "matcher": "" + } + ], + "SessionStart": [ + { + "hooks": [ + { + "command": "bd prime", + "type": "command" + } + ], + "matcher": "" + } + ] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 30b87da..2a04c86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,62 +1,5 @@ -# Dependencies -node_modules/ -.pnpm-store/ -package-lock.json -yarn.lock -# Build outputs -dist/ -build/ -*.tsbuildinfo - -# Environment -.env -.env.local -.env.*.local - -# IDE -.idea/ -.vscode/ -*.swp -*.swo - -# OS -.DS_Store -Thumbs.db - -# Logs -*.log -logs/ - -# Testing -coverage/ - -# Python -__pycache__/ -*.py[cod] -*$py.class -*.so -.venv/ -venv/ -ENV/ -env/ -.egg-info/ -*.egg-info/ -dist/ - -# Docker volumes -docker-volumes/ - -# Fusion internals -.fusion/ - -# Misc -.cache/ -.temp/ -tmp/ -.local-bin/ - -# OpenCode / Sisyphus -.opencode/ -.sisyphus/ -AGENTS.md +# Beads / Dolt files (added by bd init) +.dolt/ +*.db +.beads-credential-key diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..9390d72 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,84 @@ +# Agent Instructions + +This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context. + +## Quick Reference + +```bash +bd ready # Find available work +bd show # View issue details +bd update --claim # Claim work atomically +bd close # Complete work +bd dolt push # Push beads data to remote +``` + +## Non-Interactive Shell Commands + +**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts. + +Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input. + +**Use these forms instead:** +```bash +# Force overwrite without prompting +cp -f source dest # NOT: cp source dest +mv -f source dest # NOT: mv source dest +rm -f file # NOT: rm file + +# For recursive operations +rm -rf directory # NOT: rm -r directory +cp -rf source dest # NOT: cp -r source dest +``` + +**Other commands that may prompt:** +- `scp` - use `-o BatchMode=yes` for non-interactive +- `ssh` - use `-o BatchMode=yes` to fail instead of prompting +- `apt-get` - use `-y` flag +- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var + + +## Beads Issue Tracker + +This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands. + +### Quick Reference + +```bash +bd ready # Find available work +bd show # View issue details +bd update --claim # Claim work +bd close # Complete work +``` + +### Rules + +- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists +- Run `bd prime` for detailed command reference and session close protocol +- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files + +## Session Completion + +**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. + +**MANDATORY WORKFLOW:** + +1. **File issues for remaining work** - Create issues for anything that needs follow-up +2. **Run quality gates** (if code changed) - Tests, linters, builds +3. **Update issue status** - Close finished work, update in-progress items +4. **PUSH TO REMOTE** - This is MANDATORY: + ```bash + git pull --rebase + bd dolt push + git push + git status # MUST show "up to date with origin" + ``` +5. **Clean up** - Clear stashes, prune remote branches +6. **Verify** - All changes committed AND pushed +7. **Hand off** - Provide context for next session + +**CRITICAL RULES:** +- Work is NOT complete until `git push` succeeds +- NEVER stop before pushing - that leaves work stranded locally +- NEVER say "ready to push when you are" - YOU must push +- If push fails, resolve and retry until it succeeds + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..50af487 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,69 @@ +# Project Instructions for AI Agents + +This file provides instructions and context for AI coding agents working on this project. + + +## Beads Issue Tracker + +This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands. + +### Quick Reference + +```bash +bd ready # Find available work +bd show # View issue details +bd update --claim # Claim work +bd close # Complete work +``` + +### Rules + +- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists +- Run `bd prime` for detailed command reference and session close protocol +- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files + +## Session Completion + +**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. + +**MANDATORY WORKFLOW:** + +1. **File issues for remaining work** - Create issues for anything that needs follow-up +2. **Run quality gates** (if code changed) - Tests, linters, builds +3. **Update issue status** - Close finished work, update in-progress items +4. **PUSH TO REMOTE** - This is MANDATORY: + ```bash + git pull --rebase + bd dolt push + git push + git status # MUST show "up to date with origin" + ``` +5. **Clean up** - Clear stashes, prune remote branches +6. **Verify** - All changes committed AND pushed +7. **Hand off** - Provide context for next session + +**CRITICAL RULES:** +- Work is NOT complete until `git push` succeeds +- NEVER stop before pushing - that leaves work stranded locally +- NEVER say "ready to push when you are" - YOU must push +- If push fails, resolve and retry until it succeeds + + + +## Build & Test + +_Add your build and test commands here_ + +```bash +# Example: +# npm install +# npm test +``` + +## Architecture Overview + +_Add a brief overview of your project architecture_ + +## Conventions & Patterns + +_Add your project-specific conventions here_