diff --git a/.agent/workflows/openspec-apply.md b/.agent/workflows/openspec-apply.md deleted file mode 100644 index b0154dd..0000000 --- a/.agent/workflows/openspec-apply.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -description: Implement an approved OpenSpec change and keep tasks in sync. ---- - -**Guardrails** -- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. -- Keep changes tightly scoped to the requested outcome. -- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications. - -**Steps** -Track these steps as TODOs and complete them one by one. -1. Read `changes//proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria. -2. Work through tasks sequentially, keeping edits minimal and focused on the requested change. -3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished. -4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality. -5. Reference `openspec list` or `openspec show ` when additional context is required. - -**Reference** -- Use `openspec show --json --deltas-only` if you need additional context from the proposal while implementing. - diff --git a/.agent/workflows/openspec-archive.md b/.agent/workflows/openspec-archive.md deleted file mode 100644 index 38dcc81..0000000 --- a/.agent/workflows/openspec-archive.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -description: Archive a deployed OpenSpec change and update specs. ---- - -**Guardrails** -- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. -- Keep changes tightly scoped to the requested outcome. -- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications. - -**Steps** -1. Determine the change ID to archive: - - If this prompt already includes a specific change ID (for example inside a `` block populated by slash-command arguments), use that value after trimming whitespace. - - If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends. - - Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding. - - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet. -2. Validate the change ID by running `openspec list` (or `openspec show `) and stop if the change is missing, already archived, or otherwise not ready to archive. -3. Run `openspec archive --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work). -4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`. -5. Validate with `openspec validate --strict` and inspect with `openspec show ` if anything looks off. - -**Reference** -- Use `openspec list` to confirm change IDs before archiving. -- Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off. - diff --git a/.agent/workflows/openspec-proposal.md b/.agent/workflows/openspec-proposal.md deleted file mode 100644 index db8a95a..0000000 --- a/.agent/workflows/openspec-proposal.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -description: Scaffold a new OpenSpec change and validate strictly. ---- - -**Guardrails** -- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. -- Keep changes tightly scoped to the requested outcome. -- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications. -- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files. -- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval. - -**Steps** -1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification. -2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes//`. -3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing. -4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs. -5. Draft spec deltas in `changes//specs//spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant. -6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work. -7. Validate with `openspec validate --strict` and resolve every issue before sharing the proposal. - -**Reference** -- Use `openspec show --json --deltas-only` or `openspec show --type spec` to inspect details when validation fails. -- Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones. -- Explore the codebase with `rg `, `ls`, or direct file reads so proposals align with current implementation realities. - diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..f33e400 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "ask": [ + "Bash(git push *)" + ], + "deny": [ + "Bash(git push *--no-verify*)", + "Bash(docker push *)" + ] + } +} diff --git a/.claudeignore b/.claudeignore deleted file mode 100644 index 5391107..0000000 --- a/.claudeignore +++ /dev/null @@ -1,58 +0,0 @@ -# Spec Kitty Configuration and Templates -# These are internal directories that shouldn't be scanned by AI assistants - -# Template directories (not working code) -.kittify/templates/ -.kittify/missions/ -.kittify/scripts/ - -# Agent command directories (generated from templates, not source) -.claude/ -.codex/ -.gemini/ -.cursor/ -.qwen/ -.opencode/ -.windsurf/ -.kilocode/ -.augment/ -.roo/ -.amazonq/ -.github/copilot/ - -# Git metadata -.git/ - -# Build artifacts and caches -__pycache__/ -*.pyc -*.pyo -.pytest_cache/ -.coverage -htmlcov/ -node_modules/ -dist/ -build/ -*.egg-info/ - -# Virtual environments -.venv/ -venv/ -env/ - -# OS-specific files -.DS_Store -Thumbs.db -desktop.ini - -# IDE directories -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# Logs and databases -*.log -*.db -*.sqlite diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 07ef88a..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -kitty-specs/**/status.events.jsonl merge=spec-kitty-event-log diff --git a/.gitignore b/.gitignore index ba14d7f..8d9dea7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,31 +10,8 @@ __pycache__/ # Temp files composer.json.tmp -# Added by Spec Kitty CLI (auto-managed) -.claude/ -.codex/ -.vibe/ -.opencode/ -.windsurf/ -.gemini/ -.cursor/ -.qwen/ -.kilocode/ -.augment/ -.roo/ -.amazonq/ -.kiro/ -.agent/ -.github/copilot/ -.kittify/.dashboard -.kittify/charter/context-state.json -.kittify/charter/directives.yaml -.kittify/charter/governance.yaml -.kittify/charter/metadata.yaml -.kittify/charter/references.yaml -.kittify/dossiers/ -.kittify/events/ -.kittify/merge-state.json -.kittify/missions/__pycache__/ -.kittify/runtime/ -.kittify/workspaces/ +# .claude/settings.json is shared team configuration and is committed; only +# personal overrides stay private. https://code.claude.com/docs/en/claude-directory +**/.claude/settings.local.json +CLAUDE.local.md +.claude/agent-memory-local/ diff --git a/.kittify/charter/charter.md b/.kittify/charter/charter.md deleted file mode 100644 index 1898eff..0000000 --- a/.kittify/charter/charter.md +++ /dev/null @@ -1,77 +0,0 @@ -# Project Charter - - - -Generated: 2026-05-07T16:47:53Z - -## Testing Standards - -- Integration tests are BATS scripts that run against a live staging Coder instance (staging-coder.ddev.com) before any deployment to production. Plan-level tests use `terraform test` (no real infrastructure required). CI also runs `terraform fmt -check -recursive` and `terraform validate` for each touched template. There is no unit-test coverage percentage target — correctness is verified by staging promotion. - - -## Quality Gates - -- All changes require a pull request. CI must pass before merge. CI gates: `terraform fmt -check`, `terraform validate`, `terraform test` for each template. Integration test scripts run against staging before promoting to production. No direct commits to main. - - -## Performance Benchmarks - -- No quantitative latency targets. Workspace startup should complete within a reasonable time (under 5 minutes) as a qualitative target. CLI commands (terraform, make) should not timeout during CI runs. - - -## Branch Strategy - -- Every change requires a pull request. Single maintainer project currently, but PRs still required for traceability and CI gating. Conventional commit messages are preferred. - -- Deployment constraints: Two environments: staging-coder.ddev.com and production coder.ddev.com. Templates are promoted staging → production only after integration tests pass on staging. The main branch reflects the production-ready state. Feature branches are used for all development work. - - -## Governance Activation - -```yaml -mission: software-dev -selected_paradigms: [] -selected_directives: [] -available_tools: [git, spec-kitty] -template_set: software-dev-default -``` - -## Policy Summary - -- Intent: Manage and deploy coder.ddev.com — a cloud-hosted DDEV environment for web developers. The project owns the Coder workspace templates (Terraform HCL), the base Docker image, and the supporting shell scripts that enable Docker-in-Docker development via Sysbox runtime. A breaking change means developers cannot create or use workspaces; risk level is high for end users who depend on the service. - -- Languages/Frameworks: Terraform (HCL), Shell (Bash), Dockerfile (Ubuntu 24.04 base), bats-core (BATS test framework for shell-level integration tests), Go toolchain (available in image for future use). - -- Testing: Integration tests are BATS scripts that run against a live staging Coder instance (staging-coder.ddev.com) before any deployment to production. Plan-level tests use `terraform test` (no real infrastructure required). CI also runs `terraform fmt -check -recursive` and `terraform validate` for each touched template. There is no unit-test coverage percentage target — correctness is verified by staging promotion. - -- Quality Gates: All changes require a pull request. CI must pass before merge. CI gates: `terraform fmt -check`, `terraform validate`, `terraform test` for each template. Integration test scripts run against staging before promoting to production. No direct commits to main. - -- Review Policy: Every change requires a pull request. Single maintainer project currently, but PRs still required for traceability and CI gating. Conventional commit messages are preferred. - -- Performance Targets: No quantitative latency targets. Workspace startup should complete within a reasonable time (under 5 minutes) as a qualitative target. CLI commands (terraform, make) should not timeout during CI runs. - -- Deployment Constraints: Two environments: staging-coder.ddev.com and production coder.ddev.com. Templates are promoted staging → production only after integration tests pass on staging. The main branch reflects the production-ready state. Feature branches are used for all development work. - - -## Project Directives - -1. Respect risk boundaries: High-risk changes: modifications to startup scripts, Sysbox runtime configuration, Docker daemon setup, or base image layers — these affect all workspaces. Medium-risk: template variable changes or new templates. Low-risk: documentation, Makefile targets, version bumps. Any change that affects running workspaces requires staging validation. - -2. Keep documentation synchronized with workflow and behavior changes. - -## Reference Index - -| Reference ID | Kind | Summary | Local Doc | -|---|---|---|---| -| `USER:PROJECT_PROFILE` | user_profile | Project-specific interview answers captured for charter compilation. | `_LIBRARY/user-project-profile.md` | -| `TEMPLATE_SET:software-dev-default` | template_set | Build high-quality software with structured workflows and test-driven development | `_LIBRARY/template-set-software-dev-default.md` | - -## Amendment Process - -Charter amendments follow the same PR process as code changes. Significant governance changes should be discussed in the PR description. - - -## Exception Policy - -Hotfixes for production incidents may bypass staging testing with explicit maintainer acknowledgment in the PR, but must still pass CI. - diff --git a/.kittify/charter/interview/answers.yaml b/.kittify/charter/interview/answers.yaml deleted file mode 100644 index 333c05e..0000000 --- a/.kittify/charter/interview/answers.yaml +++ /dev/null @@ -1,79 +0,0 @@ -schema_version: "1.0.0" -mission: "software-dev" -profile: "comprehensive" -answers: - project_intent: > - Manage and deploy coder.ddev.com — a cloud-hosted DDEV environment for - web developers. The project owns the Coder workspace templates (Terraform HCL), - the base Docker image, and the supporting shell scripts that enable - Docker-in-Docker development via Sysbox runtime. A breaking change means - developers cannot create or use workspaces; risk level is high for end users - who depend on the service. - - languages_frameworks: > - Terraform (HCL), Shell (Bash), Dockerfile (Ubuntu 24.04 base), - bats-core (BATS test framework for shell-level integration tests), - Go toolchain (available in image for future use). - - testing_requirements: > - Integration tests are BATS scripts that run against a live staging Coder - instance (staging-coder.ddev.com) before any deployment to production. - Plan-level tests use `terraform test` (no real infrastructure required). - CI also runs `terraform fmt -check -recursive` and `terraform validate` - for each touched template. There is no unit-test coverage percentage target — - correctness is verified by staging promotion. - - quality_gates: > - All changes require a pull request. CI must pass before merge. - CI gates: `terraform fmt -check`, `terraform validate`, `terraform test` - for each template. Integration test scripts run against staging before - promoting to production. No direct commits to main. - - review_policy: > - Every change requires a pull request. Single maintainer project currently, - but PRs still required for traceability and CI gating. Conventional commit - messages are preferred. - - performance_targets: > - No quantitative latency targets. Workspace startup should complete within - a reasonable time (under 5 minutes) as a qualitative target. CLI commands - (terraform, make) should not timeout during CI runs. - - deployment_constraints: > - Two environments: staging-coder.ddev.com and production coder.ddev.com. - Templates are promoted staging → production only after integration tests - pass on staging. The main branch reflects the production-ready state. - Feature branches are used for all development work. - - documentation_policy: > - User-facing documentation lives in /docs/. CLAUDE.md documents developer - and contributor guidance. Changes to template behavior or CLI commands - must be reflected in docs before merge. Doc-only changes are low-risk - but still require PRs. - - risk_boundaries: > - High-risk changes: modifications to startup scripts, Sysbox runtime - configuration, Docker daemon setup, or base image layers — these affect - all workspaces. Medium-risk: template variable changes or new templates. - Low-risk: documentation, Makefile targets, version bumps. - Any change that affects running workspaces requires staging validation. - - amendment_process: > - Charter amendments follow the same PR process as code changes. - Significant governance changes should be discussed in the PR description. - - exception_policy: > - Hotfixes for production incidents may bypass staging testing with explicit - maintainer acknowledgment in the PR, but must still pass CI. - -selected_paradigms: [] - -selected_directives: [] - -available_tools: - - git - - spec-kitty - - terraform - - docker - - make - - bats diff --git a/.kittify/config.yaml b/.kittify/config.yaml deleted file mode 100644 index f8e6581..0000000 --- a/.kittify/config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -vcs: - type: git -agents: - available: - - claude - auto_commit: true -project: - uuid: 595dcc83-8eee-4a87-8644-84d94a4b531c - slug: coder-ddev - node_id: a1b8182ad705 - build_id: ea439b9d-ce91-4e8c-a458-0f28a54b80bc diff --git a/.kittify/memory/templates/POWERSHELL_SYNTAX.md b/.kittify/memory/templates/POWERSHELL_SYNTAX.md deleted file mode 100644 index a2f1d2d..0000000 --- a/.kittify/memory/templates/POWERSHELL_SYNTAX.md +++ /dev/null @@ -1,245 +0,0 @@ -# PowerShell Syntax Guide for AI Agents - -**⚠️ READ THIS if you are working in a PowerShell environment** - -This guide helps AI agents use correct PowerShell syntax when working with spec-kitty workflows. - ---- - -## Quick Reference: Bash vs PowerShell - -| Task | ❌ Bash (WRONG) | ✅ PowerShell (CORRECT) | -|------|-----------------|-------------------------| -| **Command chaining** | `cmd1 && cmd2` | `cmd1; cmd2` | -| **Parameter flags** | `--json --paths-only` | `-Json -PathsOnly` | -| **Script path** | `./scripts/bash/script.sh` | `..\scripts\powershell\Script.ps1` | -| **Environment variable** | `$VAR_NAME` | `$env:VAR_NAME` | -| **Current directory** | `pwd` | `Get-Location` (or `pwd` alias) | -| **List files** | `ls -la` | `Get-ChildItem` (or `ls` alias) | -| **File exists check** | `[ -f file.txt ]` | `Test-Path file.txt` | -| **Directory separator** | `/path/to/file` | `\path\to\file` | -| **Home directory** | `~/projects` | `$HOME\projects` | - ---- - -## Location Verification (PowerShell) - -**Check your current location:** - -```powershell -Get-Location -git branch --show-current -``` - -**Expected for mission worktrees:** - -- Location: `C:\Users\...\project\.worktrees\001-mission-name` -- Branch: `001-mission-name` (NOT `main`) - ---- - -## Running Spec-Kitty Commands (PowerShell) - -### Using the spec-kitty CLI - -Spec-kitty uses a Python CLI that works across all platforms: - -**Common commands:** - -- `spec-kitty agent mission create-mission ` - Create a new feature -- `spec-kitty verify-setup` - Check environment and paths -- `spec-kitty agent workflow implement --agent ` - Start implementing a work package -- `spec-kitty agent workflow review --agent ` - Start reviewing a work package -- `spec-kitty agent tasks move-task --to for_review` - Complete implementation (move to review) -- `spec-kitty merge` - Merge completed mission - -### Parameter Naming Convention - -PowerShell uses **PascalCase** with leading dash: - -- `-Json` (not `--json`) -- `-MissionName` (not `--mission-name`) -- `-IncludeTasks` (not `--include-tasks`) -- `-RequireTasks` (not `--require-tasks`) - -### Examples - -**Create feature:** - -```powershell -.\.kittify\scripts\powershell\Create-NewMission.ps1 ` - -MissionName "User Authentication" ` - -FeatureDescription "Add login and registration" -``` - -**Check prerequisites:** - -```powershell -.\.kittify\scripts\powershell\check-prerequisites.ps1 -Json -IncludeTasks -``` - -**Move task to review (after implementation):** - -```powershell -# Using the CLI (recommended): -spec-kitty agent tasks move-task WP01 --to for_review --note "Ready for review" - -# Or using PowerShell script: -.\.kittify\scripts\powershell\Move-TaskToLane.ps1 ` - -Feature "001-auth" ` - -TaskId "WP01" ` - -Lane "for_review" ` - -ShellPid $PID ` - -Agent "claude" -``` - ---- - -## Common Mistakes to Avoid - -### ❌ Don't Use Bash Operators - -```powershell -# WRONG: -cd worktrees && pwd - -# CORRECT: -cd worktrees; Get-Location -``` - -### ❌ Don't Use Bash-Style Parameters - -```powershell -# WRONG: -.\check-prerequisites.ps1 --json --require-tasks - -# CORRECT: -.\check-prerequisites.ps1 -Json -RequireTasks -``` - -### Path Separators in PowerShell - -PowerShell on Windows uses backslashes for native paths: - -```powershell -# WRONG (Unix-style paths on Windows): -cd ./.kittify/memory - -# CORRECT (Windows-style paths): -cd .\.kittify\memory -``` - -Note: Git commands work with forward slashes, but native PowerShell file operations expect backslashes. The spec-kitty CLI handles this automatically. - ---- - -## Environment Variables - -**Setting variables:** - -```powershell -$env:SPEC_KITTY_TEMPLATE_ROOT = "C:\path\to\spec-kitty" -``` - -**Reading variables:** - -```powershell -echo $env:SPEC_KITTY_TEMPLATE_ROOT -``` - -**Checking if set:** - -```powershell -if ($env:SPEC_KITTY_TEMPLATE_ROOT) { - Write-Host "Variable is set" -} -``` - ---- - -## File Operations - -**Check if file exists:** - -```powershell -if (Test-Path "spec.md") { - Write-Host "Spec exists" -} -``` - -**Read file:** - -```powershell -$content = Get-Content "spec.md" -Raw -``` - -**Create directory:** - -```powershell -New-Item -ItemType Directory -Path "tasks\planned" -Force -``` - ---- - -## Workflow Tips - -1. **Always use full parameter names** in scripts (not abbreviations) -2. **Use semicolons** to chain commands, not `&&` or `||` -3. **Backslashes** for local paths, forward slashes OK for git operations -4. **$PID** contains current PowerShell process ID (use for --shell-pid) -5. **Tab completion** works for parameter names in PowerShell - ---- - -## When to Use What - -**Use PowerShell scripts when:** - -- User specified `--script ps` during init -- You're in a Windows PowerShell terminal -- Templates reference `.ps1` files in frontmatter - -**Use Bash scripts when:** - -- User specified `--script sh` during init -- You're in bash/zsh/fish terminal -- Templates reference `.sh` files in frontmatter - -**Using spec-kitty commands:** -All spec-kitty commands work the same way on PowerShell and Bash: - -```powershell -spec-kitty agent workflow implement WP01 --agent claude # Auto-moves to doing -spec-kitty agent tasks move-task WP01 --to for_review # Completion step -spec-kitty verify-setup -spec-kitty dashboard -``` - -The CLI is cross-platform and handles path differences automatically. - ---- - -## Debugging PowerShell Issues - -**Common errors and solutions:** - -1. **"Parameter cannot be found that matches parameter name"** - - You used bash-style parameters (`--json`) - - Fix: Use PowerShell style (`-Json`) - -2. **"The term '&&' is not recognized"** - - You used bash command chaining - - Fix: Use semicolon (`;`) instead - -3. **"Cannot find path"** - - You used forward slashes in PowerShell path - - Fix: Use backslashes (`\`) for local paths - -4. **"Unable to import mission module"** - - Python can't find specify_cli package - - Check: `pip show spec-kitty-cli` - - Fix: Reinstall or check virtual environment - ---- - -**For full spec-kitty documentation, see the main templates and README.** diff --git a/.kittify/metadata.yaml b/.kittify/metadata.yaml deleted file mode 100644 index 1863372..0000000 --- a/.kittify/metadata.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Spec Kitty Project Metadata -# Auto-generated by spec-kitty init/upgrade -# DO NOT EDIT MANUALLY - -spec_kitty: - version: 3.1.8 - initialized_at: '2026-05-07T10:43:17.519511' - last_upgraded_at: null -environment: - python_version: 3.14.4 - platform: darwin - platform_version: macOS-26.4.1-arm64-arm-64bit-Mach-O -migrations: - applied: [] diff --git a/.kittify/skills-manifest.json b/.kittify/skills-manifest.json deleted file mode 100644 index 5a35257..0000000 --- a/.kittify/skills-manifest.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "version": 1, - "created_at": "2026-05-07T16:43:17.476272+00:00", - "updated_at": "2026-05-07T16:43:17.506903+00:00", - "spec_kitty_version": "3.1.8", - "entries": [ - { - "skill_name": "ad-hoc-profile-load", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/ad-hoc-profile-load/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:85acce1cc660cdec6f0fe8fd669d82b393572d9c5cda561ffd17df3f7b59fc5e", - "installed_at": "2026-05-07T16:43:17.480986+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-bulk-edit-classification", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-bulk-edit-classification/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:30e444e44afc5db2b44c8a57627f9f69537816d8c7c9fea7049efed71cdd410e", - "installed_at": "2026-05-07T16:43:17.482823+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-charter-doctrine", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-charter-doctrine/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:c46f7804b175a3e185bf7d22f792bd80b1e67f798d8f9fc40ee58964838e1da0", - "installed_at": "2026-05-07T16:43:17.485117+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-charter-doctrine", - "source_file": "references/charter-command-map.md", - "installed_path": ".claude/skills/spec-kitty-charter-doctrine/references/charter-command-map.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:8d2cccd8dc727cb9ba78c2e9bf3559e83cdf93d6a632970254c9ae6b8b5733db", - "installed_at": "2026-05-07T16:43:17.485117+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-charter-doctrine", - "source_file": "references/doctrine-artifact-structure.md", - "installed_path": ".claude/skills/spec-kitty-charter-doctrine/references/doctrine-artifact-structure.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:f771e9e9e98d65aa4380b94e3f6a24e08d6c2cd3ca44ca1cba3bd14283af9f17", - "installed_at": "2026-05-07T16:43:17.485117+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-git-workflow", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-git-workflow/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:631f90114af7e9d108a58741af46dcd08163f3a814cbb9d95c905c19d337cc60", - "installed_at": "2026-05-07T16:43:17.487395+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-git-workflow", - "source_file": "references/git-operations-matrix.md", - "installed_path": ".claude/skills/spec-kitty-git-workflow/references/git-operations-matrix.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:6bb45291ff5ce626eaadde3a6e4a4c8d69577b3c4698c4551d251f293c66bfaa", - "installed_at": "2026-05-07T16:43:17.487395+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-glossary-context", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-glossary-context/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:e9592a088d2d6d2e2ecf65eaa6a8d31f0dbe1e6f4236d5747d6fe26ea980e89e", - "installed_at": "2026-05-07T16:43:17.489912+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-glossary-context", - "source_file": "references/glossary-field-guide.md", - "installed_path": ".claude/skills/spec-kitty-glossary-context/references/glossary-field-guide.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:9cddfccd64773976cf97450fa983dc8cc3aa7354a6002d763a7fa3ac65ff9ace", - "installed_at": "2026-05-07T16:43:17.489912+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-glossary-context", - "source_file": "references/semantic-drift-examples.md", - "installed_path": ".claude/skills/spec-kitty-glossary-context/references/semantic-drift-examples.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:d2df36b399316d12d05b10b36dab19a3eb330ed9c502b9b0fa2bb35ecf8341c4", - "installed_at": "2026-05-07T16:43:17.489912+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-implement-review", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-implement-review/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:6977839d92e84b4fb5da00e1c665003a95ead5fba92eaa9254ec78d074842f98", - "installed_at": "2026-05-07T16:43:17.492386+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-implement-review", - "source_file": "references/agent-dispatch-matrix.md", - "installed_path": ".claude/skills/spec-kitty-implement-review/references/agent-dispatch-matrix.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:94a2ddfb52a2b1da85e286221e580fd49d94cbb4e2a716fe02f4b76897c30ed0", - "installed_at": "2026-05-07T16:43:17.492386+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-implement-review", - "source_file": "references/rejection-loop-checklist.md", - "installed_path": ".claude/skills/spec-kitty-implement-review/references/rejection-loop-checklist.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:dcf6ffa8a173a5ea937a74fd1af4c0427f595008a00d91b5a7970a13f2e202ab", - "installed_at": "2026-05-07T16:43:17.492386+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-mission-review", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-mission-review/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:45ba9f04c2b9b337b7c27249a9779eb8613c0450ddd46adb12c11c02eaa80b5f", - "installed_at": "2026-05-07T16:43:17.494574+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-mission-review", - "source_file": "references/mission-review-fr-trace-guide.md", - "installed_path": ".claude/skills/spec-kitty-mission-review/references/mission-review-fr-trace-guide.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:4ae2391cd2e4c3bdb32a25e7a8476612fb1b94d156a4250701c9f537e011f0fd", - "installed_at": "2026-05-07T16:43:17.494574+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-mission-system", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-mission-system/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:b0172954384382df472ae94ae8754d1d98621530e1ae41336c1883a2827aafd0", - "installed_at": "2026-05-07T16:43:17.496533+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-mission-system", - "source_file": "references/mission-comparison-matrix.md", - "installed_path": ".claude/skills/spec-kitty-mission-system/references/mission-comparison-matrix.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:068063581aa360dcf114b32b65b31531367d4a7feacca7d607685a3862bfa3f4", - "installed_at": "2026-05-07T16:43:17.496533+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-orchestrator-api-operator", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-orchestrator-api-operator/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:750b35e440410841c41d811f26a59a3838b03458ff595b01ba594e9997ed2dd0", - "installed_at": "2026-05-07T16:43:17.499018+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-orchestrator-api-operator", - "source_file": "references/host-boundary-rules.md", - "installed_path": ".claude/skills/spec-kitty-orchestrator-api-operator/references/host-boundary-rules.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:fa806c1d0a1446b54ae589ea00f3edc55495bfaf43f801c90ca0872380e77fb0", - "installed_at": "2026-05-07T16:43:17.499018+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-orchestrator-api-operator", - "source_file": "references/orchestrator-api-contract.md", - "installed_path": ".claude/skills/spec-kitty-orchestrator-api-operator/references/orchestrator-api-contract.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:be5c0536a854771ace6c89db4e7b2f96c5f96e1f9a126f8a088941c1088c3a2d", - "installed_at": "2026-05-07T16:43:17.499018+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-runtime-next", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-runtime-next/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:4556cc9de0c88cf4b3b301b23b51deb39ed1338eecd5ee858988042d9dcc78aa", - "installed_at": "2026-05-07T16:43:17.501463+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-runtime-next", - "source_file": "references/blocked-state-recovery.md", - "installed_path": ".claude/skills/spec-kitty-runtime-next/references/blocked-state-recovery.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:787304873d5e8e254ea90ffd81e5af9d8d3c859a0688c7431f40fe4a3c20aa59", - "installed_at": "2026-05-07T16:43:17.501463+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-runtime-next", - "source_file": "references/runtime-result-taxonomy.md", - "installed_path": ".claude/skills/spec-kitty-runtime-next/references/runtime-result-taxonomy.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:80365f9eca8f07cd96a85aad55247707e90765caddc24037f1a60de4053df2fe", - "installed_at": "2026-05-07T16:43:17.501463+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-runtime-review", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-runtime-review/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:fd994f73054a11e98de7871526ea96df6e580e22e21a3b51d928498aaca02d6a", - "installed_at": "2026-05-07T16:43:17.503446+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-runtime-review", - "source_file": "references/review-checklist.md", - "installed_path": ".claude/skills/spec-kitty-runtime-review/references/review-checklist.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:9279016c3b96e71fbd5d06cbaedf719307fd4497afe1673af7a613a4e38b93ab", - "installed_at": "2026-05-07T16:43:17.503446+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-setup-doctor", - "source_file": "SKILL.md", - "installed_path": ".claude/skills/spec-kitty-setup-doctor/SKILL.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:8fb297bcb646a41abb0b8a024d842a956297ab12366bc6285a5bcacb880c6fb7", - "installed_at": "2026-05-07T16:43:17.506324+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-setup-doctor", - "source_file": "references/agent-path-matrix.md", - "installed_path": ".claude/skills/spec-kitty-setup-doctor/references/agent-path-matrix.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:6128bd3a1994467c24c168b9b998aa0b7c0d31a5f112c12aff4bebc5915416ff", - "installed_at": "2026-05-07T16:43:17.506324+00:00", - "delivery_mode": "symlink" - }, - { - "skill_name": "spec-kitty-setup-doctor", - "source_file": "references/common-failure-signatures.md", - "installed_path": ".claude/skills/spec-kitty-setup-doctor/references/common-failure-signatures.md", - "installation_class": "native-root-required", - "agent_key": "claude", - "content_hash": "sha256:fc5ccc9248a290f23507556d6cd25e2c38a63f8cba4cf4f40897735fd489198f", - "installed_at": "2026-05-07T16:43:17.506324+00:00", - "delivery_mode": "symlink" - } - ] -} diff --git a/AGENTS.md b/AGENTS.md index 0669699..5d62a57 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,18 +1,383 @@ - -# OpenSpec Instructions +# AGENTS.md -These instructions are for AI assistants working in this project. +Guidance for AI agents working on the coder-ddev codebase. Claude Code reads +this file directly; there is no `CLAUDE.md`. -Always open `@/openspec/AGENTS.md` when the request: -- Mentions planning or proposals (words like proposal, spec, change, plan) -- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work -- Sounds ambiguous and you need the authoritative spec before coding +DDEV's [organization-wide patterns](https://raw.githubusercontent.com/ddev/.github/main/AGENTS.md) +(boundaries, writing style, branches, commits, PRs and issues) apply here too. +This file **wins where they differ**. Fetch GitHub files through +`raw.githubusercontent.com`, not `github.com/.../blob/...` pages, which wrap +the file in markup. -Use `@/openspec/AGENTS.md` to learn: -- How to create and apply change proposals -- Spec format and conventions -- Project structure and guidelines +## Claude Code automation -Keep this managed block so 'openspec update' can refresh the instructions. +`.claude/settings.json` applies only to Claude Code; other agents follow the +rules below by hand. With it, `git push` asks for approval every time, in +every permission mode, and `git push --no-verify` and `docker push` are +denied. Personal overrides go in `.claude/settings.local.json` or +`CLAUDE.local.md`, both gitignored; a `CLAUDE.local.md` can stop Claude Code +from loading this file, so add an `@AGENTS.md` import to it if you use one. - \ No newline at end of file +## Overview + +This project provides a Coder v2+ template for DDEV-based development environments using Docker-in-Docker via Sysbox runtime. It creates isolated workspaces with full Docker daemon support for running DDEV projects. + +**Key Technologies:** +- **Terraform (HCL)** - Infrastructure as Code for Coder templates +- **Docker + Sysbox** - Nested containerization without privileged mode +- **DDEV** - PHP/Node/Python development environment tool (supports 20+ project types) +- **VS Code for Web** - Browser-based IDE via official Coder module +- **Ubuntu 24.04** - Base container OS + +**Note:** User-facing documentation lives in `/docs/`. This file focuses on developer/contributor guidance. + +## Coder CLI Commands in Docs + +When writing or reviewing `coder` CLI commands in documentation, **always verify against the actual CLI** (`coder --help`) and the [Coder CLI reference docs](https://coder.com/docs/reference/cli). Common past mistakes to avoid: + +- `coder delete` takes only **one** workspace argument — use a `for` loop for multiple +- `coder stop` / `coder start` take only **one** workspace argument +- `coder scp` does **not exist** — use `scp` after `coder config-ssh` +- `coder templates show` does **not exist** — use `coder templates list -o json | jq ...` +- `coder publickey` has no `add`/`list`/`remove` subcommands — it only outputs your key +- `coder list` has no `--user` flag — use `--search "owner:"` with `-a` +- `coder tokens` uses `remove` not `revoke`; `create` takes `--name`, not a positional arg +- `coder templates list` has no `--organization` flag — use the global `--org` +- `coder sharing add` requires `--user :` (role required) +- `coder update --parameter X=Y` / `coder restart --parameter X=Y` **silently no-op** on the parameter unless `--always-prompt` is also passed — without it, Coder just reuses the workspace's existing value and (for `update`) may skip the rebuild entirely if the template version hasn't changed. With `--always-prompt`, every *mutable* parameter must be supplied via `--parameter` or it falls back to the template default via `--use-parameter-defaults` (not the workspace's current value) — and any *immutable* parameter (e.g. drupal-contrib's `project_name`) must be **omitted entirely**, since `--always-prompt` errors trying to "change" it even to its current value. Verified live against staging-coder.ddev.com while building the sharing feature (see PR for #204). +- `coder create`/`coder update`/`coder restart --parameter name=value` **splits the value on commas** (it's a `string-array` flag) — a parameter whose value legitimately contains a comma (e.g. freeform's `project_names="a,b"`) fails with `unable to parse rich parameters: format key=value expected, but got b`. Use `--rich-parameter-file ` instead for any comma-containing value; this bit CI on the first attempt at the freeform sharing test (PR #205). + +## DDEV Command Gotchas + +- `ddev composer create` is **obsolete** — always use `ddev composer create-project .` (note the trailing `.` for current directory) +- Do **not** pin packages to `:dev-main` (e.g. `package:dev-main`) — omit the version constraint and let Composer resolve it +- All templates omit `ddev-router` via `ddev config global --omit-containers=ddev-router`; each template uses direct port binding instead + +## Coder Parameter Gotchas + +- **Never change an existing `coder_parameter`'s `type` in place — always give it a new `name`.** The `coder_parameter` data source validates the incoming value against the declared `type` *before* any of the template's own `locals` ever run, so a `try(tobool(...), false)`-style fallback in a `locals` block cannot rescue a stale value — the plan fails hard first, with an opaque `Error: Parameter value is not of type "bool"`. Any client still holding an old-typed value for that parameter name (a bookmarked workspace-creation deep link, a cached copy of a `docs/*.html` page, an already-open browser tab) will hit this on every future `terraform plan`, including the Coder UI's live dynamic-parameter preview during workspace creation. Renaming the parameter is the only fix — `terraform` code cannot intercept the provider's own type validation. Root-caused and fixed for `share_drupal_site` → `drupal_site_public` in #206 (`drupal-core`/`drupal-contrib`; both changed the parameter from a 3-way `owner`/`authenticated`/`public` string to a `bool` switch in #205, one PR earlier — the type change and the deep-link doc pages that still emitted the old string values shipped in the same PR and nothing caught the mismatch). +- **`terraform test`'s `mock_provider "coder"` cannot catch the above class of bug.** The mock replaces the real `coder_parameter` data source entirely (including its type validation), so a run block asserting behavior for a stale/incompatible parameter value will pass locally and in CI even when the real provider would hard-fail. There is no terraform-test-layer way to close this gap; the only defense is the naming discipline above. +- **`docs/drupal-core.html`, `docs/drupal-issue.html`, and `docs/coder-workspace-name.js` build Coder workspace-creation deep links (`?param.=`) and are not covered by any CI check against the live `coder_parameter` definitions in `template.tf`.** Whenever a template's parameter names, types, or allowed values change, grep these docs files for the old name/values and update them in the same PR — nothing currently fails CI if they drift out of sync. + +## Template Architecture Overview + +Three templates exist, each with a distinct routing model: + +| Template | Web port | Routing model | +| -------------------- | -------- | ----------------------------------------------------- | +| `drupal-core` | 80 | Direct bind, no ddev-router | +| `drupal-contrib` | 8080 | Direct bind, no ddev-router | +| `freeform` | 8080 | ddev-router on 8080, Host-header dispatch per project | + +The `freeform` template is unique: it keeps ddev-router running so multiple DDEV projects can coexist in one workspace, distinguished by Host header. + +## Tool Preferences + +- Use `jq` (not `python3 -m json.tool`) for JSON pretty-printing and querying +- For `git commit -m` and `gh pr create --body`, write the message to a file first (e.g. under the scratchpad directory) and pass it via `git commit -F ` / `gh pr create --body-file `, rather than inlining a heredoc on the command line. Multi-paragraph messages containing backticks, apostrophes, or other shell-special characters reliably break inline heredoc quoting. + +## Before Pushing / Pre-push Checklist + +Run these before every push to avoid CI failures: + +```bash +# Terraform formatting (CI runs terraform fmt -check -recursive) +terraform fmt -recursive + +# Vendor shared assets, then validate + test every template +make validate +make test-templates +``` + +`terraform fmt -recursive` must be run from the repo root. It is non-destructive (rewrites in place) and the CI check fails with exit code 3 if any file is not formatted. + +**Always use `make validate` / `make test-templates`, not raw `terraform validate`/`terraform test` run directly in a template directory.** Both targets depend on `make sync-shared`, which vendors `modules/claude-remote-control` and `shared/vscode-extensions.tf` into each template directory first (see "Shared Terraform Assets" below). Running `terraform validate`/`test` directly against a template dir will happily validate against a stale vendored copy and miss the fact that it's out of sync with the canonical source. + +## Shared Terraform Assets + +Some Terraform config (currently `modules/claude-remote-control`, `modules/docker-daemon`, `shared/vscode-extensions.tf`, `shared/bashrc-symlink-guard.sh` and `shared/ssh-agent-setup.sh`) is shared across all three templates but must exist as a **physical copy inside each template directory** — `coder templates push` and CI's `terraform validate`/`test` only ever operate on a single template directory, so a relative `../modules` or `../shared` reference would not survive the push and would not be visible to CI. + +`modules/claude-self-hosted-runner` follows the same rules but is vendored into `freeform` only, the one template that offers the runner. + +- **Edit only the canonical source**: `modules/claude-remote-control/` or `shared/vscode-extensions.tf` at the repo root. Never hand-edit the vendored copies (`