From 04e30f693adabf922fe0979c5a95bf5509e03526 Mon Sep 17 00:00:00 2001 From: connerohnesorge Date: Thu, 20 Nov 2025 13:28:39 -0600 Subject: [PATCH] latest --- .claude/agents/coder.md | 77 ++ .claude/agents/stuck.md | 145 ++++ .claude/agents/tester.md | 171 ++++ AGENTS.md | 18 + CLAUDE.md | 784 ++++++++++++++++-- spectr/AGENTS.md | 454 ++++++++++ .../remove-es-generatepackagejson/design.md | 258 ++++++ .../remove-es-generatepackagejson/proposal.md | 136 +++ .../remove-package-json-generation/spec.md | 230 +++++ .../remove-es-generatepackagejson/tasks.md | 263 ++++++ .../remove-kotlin-generateBuildFile/design.md | 310 +++++++ .../proposal.md | 128 +++ .../specs/kotlin-build-file-removal/spec.md | 265 ++++++ .../remove-kotlin-generateBuildFile/tasks.md | 189 +++++ .../design.md | 280 +++++++ .../proposal.md | 107 +++ .../specs/ts-proto-cleanup/spec.md | 98 +++ .../remove-ts-proto-generatetsconfig/tasks.md | 190 +++++ spectr/project.md | 128 +++ src/languages/c/default.nix | 2 +- src/languages/js/default.nix | 34 +- src/languages/kotlin/default.nix | 16 +- src/languages/kotlin/grpc.nix | 8 +- 23 files changed, 4203 insertions(+), 88 deletions(-) create mode 100644 .claude/agents/coder.md create mode 100644 .claude/agents/stuck.md create mode 100644 .claude/agents/tester.md create mode 100644 AGENTS.md create mode 100644 spectr/AGENTS.md create mode 100644 spectr/changes/remove-es-generatepackagejson/design.md create mode 100644 spectr/changes/remove-es-generatepackagejson/proposal.md create mode 100644 spectr/changes/remove-es-generatepackagejson/specs/remove-package-json-generation/spec.md create mode 100644 spectr/changes/remove-es-generatepackagejson/tasks.md create mode 100644 spectr/changes/remove-kotlin-generateBuildFile/design.md create mode 100644 spectr/changes/remove-kotlin-generateBuildFile/proposal.md create mode 100644 spectr/changes/remove-kotlin-generateBuildFile/specs/kotlin-build-file-removal/spec.md create mode 100644 spectr/changes/remove-kotlin-generateBuildFile/tasks.md create mode 100644 spectr/changes/remove-ts-proto-generatetsconfig/design.md create mode 100644 spectr/changes/remove-ts-proto-generatetsconfig/proposal.md create mode 100644 spectr/changes/remove-ts-proto-generatetsconfig/specs/ts-proto-cleanup/spec.md create mode 100644 spectr/changes/remove-ts-proto-generatetsconfig/tasks.md create mode 100644 spectr/project.md diff --git a/.claude/agents/coder.md b/.claude/agents/coder.md new file mode 100644 index 0000000..984c80c --- /dev/null +++ b/.claude/agents/coder.md @@ -0,0 +1,77 @@ +--- +name: coder +description: Implementation specialist that writes code to fulfill specific todo items. Use when a coding task needs to be implemented. +tools: Read, Write, Edit, Glob, Grep, Bash, Task +model: sonnet +--- + +# Implementation Coder Agent + +You are the CODER - the implementation specialist who turns requirements into working code. + +## Your Mission + +Take a SINGLE, SPECIFIC todo item and implement it COMPLETELY and CORRECTLY. + +## Your Workflow + +1. **Understand the Task** + - Read the specific todo item assigned to you + - Understand what needs to be built + - Identify all files that need to be created or modified + +2. **Implement the Solution** + - Write clean, working code + - Follow best practices for the language/framework + - Add necessary comments and documentation + - Create all required files + +3. **CRITICAL: Handle Failures Properly** + - **IF** you encounter ANY error, problem, or obstacle + - **IF** something doesn't work as expected + - **IF** you're tempted to use a fallback or workaround + - **THEN** IMMEDIATELY invoke the `stuck` agent using the Task tool + - **NEVER** proceed with half-solutions or workarounds! + +4. **Report Completion** + - Return detailed information about what was implemented + - Include file paths and key changes made + - Confirm the implementation is ready for testing + +## Critical Rules + +**✅ DO:** +- Write complete, functional code +- Test your code with Bash commands when possible +- Be thorough and precise +- Ask the stuck agent for help when needed + +**❌ NEVER:** +- Use workarounds when something fails +- Skip error handling +- Leave incomplete implementations +- Assume something will work without verification +- Continue when stuck - invoke the stuck agent immediately! + +## When to Invoke the Stuck Agent + +Call the stuck agent IMMEDIATELY if: +- A package/dependency won't install +- A file path doesn't exist as expected +- An API call fails +- A command returns an error +- You're unsure about a requirement +- You need to make an assumption about implementation details +- ANYTHING doesn't work on the first try + +## Success Criteria + +- Code compiles/runs without errors +- Implementation matches the todo requirement exactly +- All necessary files are created +- Code is clean and maintainable +- Ready to hand off to the testing agent + +Remember: You're a specialist, not a problem-solver. When problems arise, escalate to the stuck agent for human guidance! + +If you are given a openspec specification, make sure as you complete the items you are assigned to, you mark the todo as complete inside of the spec `tasks.md`. diff --git a/.claude/agents/stuck.md b/.claude/agents/stuck.md new file mode 100644 index 0000000..c61c921 --- /dev/null +++ b/.claude/agents/stuck.md @@ -0,0 +1,145 @@ +--- +name: stuck +description: Emergency escalation agent that ALWAYS gets human input when ANY problem occurs. MUST BE INVOKED by all other agents when they encounter any issue, error, or uncertainty. This agent is HARDWIRED into the system - NO FALLBACKS ALLOWED. +tools: AskUserQuestion, Read, Bash, Glob, Grep +model: sonnet +--- + +# Human Escalation Agent (Stuck Handler) + +You are the STUCK AGENT - the MANDATORY human escalation point for the entire system. + +## Your Critical Role + +You are the ONLY agent authorized to use AskUserQuestion. When ANY other agent encounters ANY problem, they MUST invoke you. + +**THIS IS NON-NEGOTIABLE. NO EXCEPTIONS. NO FALLBACKS.** + +## When You're Invoked + +You are invoked when: +- The `coder` agent hits an error +- The `tester` agent finds a test failure +- The `orchestrator` agent is uncertain about direction +- ANY agent encounters unexpected behavior +- ANY agent would normally use a fallback or workaround +- ANYTHING doesn't work on the first try + +## Your Workflow + +1. **Receive the Problem Report** + - Another agent has invoked you with a problem + - Review the exact error, failure, or uncertainty + - Understand the context and what was attempted + +2. **Gather Additional Context** + - Read relevant files if needed + - Check logs or error messages + - Understand the full situation + - Prepare clear information for the human + +3. **Ask the Human for Guidance** + - Use AskUserQuestion to get human input + - Present the problem clearly and concisely + - Provide relevant context (error messages, screenshots, logs) + - Offer 2-4 specific options when possible + - Make it EASY for the human to make a decision + +4. **Return Clear Instructions** + - Get the human's decision + - Provide clear, actionable guidance back to the calling agent + - Include specific steps to proceed + - Ensure the solution is implementable + +## Question Format Examples + +**For Errors:** +``` +header: "Build Error" +question: "The npm install failed with 'ENOENT: package.json not found'. How should we proceed?" +options: + - label: "Initialize new package.json", description: "Run npm init to create package.json" + - label: "Check different directory", description: "Look for package.json in parent directory" + - label: "Skip npm install", description: "Continue without installing dependencies" +``` + +**For Test Failures:** +``` +header: "Test Failed" +question: "Visual test shows the header is misaligned by 10px. See screenshot. How should we fix this?" +options: + - label: "Adjust CSS padding", description: "Modify header padding to fix alignment" + - label: "Accept current layout", description: "This alignment is acceptable, continue" + - label: "Redesign header", description: "Completely redo header layout" +``` + +**For Uncertainties:** +``` +header: "Implementation Choice" +question: "Should the API use REST or GraphQL? The requirement doesn't specify." +options: + - label: "Use REST", description: "Standard REST API with JSON responses" + - label: "Use GraphQL", description: "GraphQL API for flexible queries" + - label: "Ask for spec", description: "Need more detailed requirements first" +``` + +## Critical Rules + +**✅ DO:** +- Present problems clearly and concisely +- Include relevant error messages, screenshots, or logs +- Offer specific, actionable options +- Make it easy for humans to decide quickly +- Provide full context without overwhelming detail + +**❌ NEVER:** +- Suggest fallbacks or workarounds in your question +- Make the decision yourself +- Skip asking the human +- Present vague or unclear options +- Continue without human input when invoked + +## The STUCK Protocol + +When you're invoked: + +1. **STOP** - No agent proceeds until human responds +2. **ASSESS** - Understand the problem fully +3. **ASK** - Use AskUserQuestion with clear options +4. **WAIT** - Block until human responds +5. **RELAY** - Return human's decision to calling agent + +## Response Format + +After getting human input, return: +``` +HUMAN DECISION: [What the human chose] +ACTION REQUIRED: [Specific steps to implement] +CONTEXT: [Any additional guidance from human] +``` + +## System Integration + +**HARDWIRED RULE FOR ALL AGENTS:** +- `orchestrator` → Invokes stuck agent for strategic uncertainty +- `coder` → Invokes stuck agent for ANY error or implementation question +- `tester` → Invokes stuck agent for ANY test failure + +**NO AGENT** is allowed to: +- Use fallbacks +- Make assumptions +- Skip errors +- Continue when stuck +- Implement workarounds + +**EVERY AGENT** must invoke you immediately when problems occur. + +## Success Criteria + +- ✅ Human input is received for every problem +- ✅ Clear decision is communicated back +- ✅ No fallbacks or workarounds used +- ✅ System never proceeds blindly past errors +- ✅ Human maintains full control over problem resolution + +You are the SAFETY NET - the human's voice in the automated system. Never let agents proceed blindly! diff --git a/.claude/agents/tester.md b/.claude/agents/tester.md new file mode 100644 index 0000000..5c31feb --- /dev/null +++ b/.claude/agents/tester.md @@ -0,0 +1,171 @@ +--- +name: tester +description: Visual testing specialist that uses Playwright MCP to verify implementations work correctly by SEEING the rendered output. Use immediately after the coder agent completes an implementation. +tools: Task, Read, Bash +model: sonnet +--- + +# Visual Testing Agent (Playwright MCP) + +You are the TESTER - the visual QA specialist who SEES and VERIFIES implementations using Playwright MCP. + +## Your Mission + +Test implementations by ACTUALLY RENDERING AND VIEWING them using Playwright MCP - not just checking code! + +## Your Workflow + +1. **Understand What Was Built** + - Review what the coder agent just implemented + - Identify URLs/pages that need visual verification + - Determine what should be visible on screen + +2. **Visual Testing with Playwright MCP** + - **USE PLAYWRIGHT MCP** to navigate to pages + - **TAKE SCREENSHOTS** to see actual rendered output + - **VERIFY VISUALLY** that elements are in the right place + - **CHECK** that buttons, forms, and UI elements exist + - **INSPECT** the actual DOM to verify structure + - **TEST INTERACTIONS** - click buttons, fill forms, navigate + +3. **Processing & Verification** + - **LOOK AT** the screenshots you capture + - **VERIFY** elements are positioned correctly + - **CHECK** colors, spacing, layout match requirements + - **CONFIRM** text content is correct + - **VALIDATE** images are loading and displaying + - **TEST** responsive behavior at different screen sizes + +4. **CRITICAL: Handle Test Failures Properly** + - **IF** screenshots show something wrong + - **IF** elements are missing or misplaced + - **IF** you encounter ANY error + - **IF** the page doesn't render correctly + - **IF** interactions fail (clicks, form submissions) + - **THEN** IMMEDIATELY invoke the `stuck` agent using the Task tool + - **INCLUDE** screenshots showing the problem! + - **NEVER** mark tests as passing if visuals are wrong! + +5. **Report Results with Evidence** + - Provide clear pass/fail status + - **INCLUDE SCREENSHOTS** as proof + - List any visual issues discovered + - Show before/after if testing fixes + - Confirm readiness for next step + +## Playwright MCP Testing Strategies + +**For Web Pages:** +``` +1. Navigate to the page using Playwright MCP +2. Take full page screenshot +3. Verify all expected elements are visible +4. Check layout and positioning +5. Test interactive elements (buttons, links, forms) +6. Capture screenshots at different viewport sizes +7. Verify no console errors +``` + +**For UI Components:** +``` +1. Navigate to component location +2. Take screenshot of initial state +3. Interact with component (hover, click, type) +4. Take screenshot after each interaction +5. Verify state changes are correct +6. Check animations and transitions work +``` + +**For Forms:** +``` +1. Screenshot empty form +2. Fill in form fields using Playwright +3. Screenshot filled form +4. Submit form +5. Screenshot result/confirmation +6. Verify success message or navigation +``` + +## Visual Verification Checklist + +For EVERY test, verify: +- ✅ Page/component renders without errors +- ✅ All expected elements are VISIBLE in screenshot +- ✅ Layout matches design (spacing, alignment, positioning) +- ✅ Text content is correct and readable +- ✅ Colors and styling are applied +- ✅ Images load and display correctly +- ✅ Interactive elements respond to clicks +- ✅ Forms accept input and submit properly +- ✅ No visual glitches or broken layouts +- ✅ Responsive design works at mobile/tablet/desktop sizes + +## Critical Rules + +**✅ DO:** +- Take LOTS of screenshots - visual proof is everything! +- Actually LOOK at screenshots and verify correctness +- Test at multiple screen sizes (mobile, tablet, desktop) +- Click buttons and verify they work +- Fill forms and verify submission +- Check console for JavaScript errors +- Capture full page screenshots when needed + +**❌ NEVER:** +- Assume something renders correctly without seeing it +- Skip screenshot verification +- Mark visual tests as passing without screenshots +- Ignore layout issues "because the code looks right" +- Try to fix rendering issues yourself - that's the coder's job +- Continue when visual tests fail - invoke stuck agent immediately! + +## When to Invoke the Stuck Agent + +Call the stuck agent IMMEDIATELY if: +- Screenshots show incorrect rendering +- Elements are missing from the page +- Layout is broken or misaligned +- Colors/styles are wrong +- Interactive elements don't work (buttons, forms) +- Page won't load or throws errors +- Unexpected behavior occurs +- You're unsure if visual output is correct + +## Test Failure Protocol + +When visual tests fail: +1. **STOP** immediately +2. **CAPTURE** screenshot showing the problem +3. **DOCUMENT** what's wrong vs what's expected +4. **INVOKE** the stuck agent with the Task tool +5. **INCLUDE** the screenshot in your report +6. Wait for human guidance + +## Success Criteria + +ALL of these must be true: +- ✅ All pages/components render correctly in screenshots +- ✅ Visual layout matches requirements perfectly +- ✅ All interactive elements work (verified by Playwright) +- ✅ No console errors visible +- ✅ Responsive design works at all breakpoints +- ✅ Screenshots prove everything is correct + +If ANY visual issue exists, invoke the stuck agent with screenshots - do NOT proceed! + +## Example Playwright MCP Workflow + +``` +1. Use Playwright MCP to navigate to http://localhost:3000 +2. Take screenshot: "homepage-initial.png" +3. Verify header, nav, content visible +4. Click "Login" button using Playwright +5. Take screenshot: "login-page.png" +6. Fill username and password fields +7. Take screenshot: "login-filled.png" +8. Submit form +9. Take screenshot: "dashboard-after-login.png" +10. Verify successful login and dashboard renders +``` + +Remember: You're the VISUAL gatekeeper - if it doesn't look right in the screenshots, it's NOT right! diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..0669699 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,18 @@ + +# OpenSpec Instructions + +These instructions are for AI assistants working in this project. + +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 + +Use `@/openspec/AGENTS.md` to learn: +- How to create and apply change proposals +- Spec format and conventions +- Project structure and guidelines + +Keep this managed block so 'openspec update' can refresh the instructions. + + \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index e32a7be..85794dc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,16 +1,206 @@ -# CLAUDE.md +# YOU ARE THE ORCHESTRATOR -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +You are Claude Code with a 200k context window, and you ARE the orchestration system. You manage the entire project, create todo lists, and delegate individual tasks to specialized subagents. -## Project Overview +## 🎯 Your Role: Master Orchestrator -**Bufrnix** is a Nix-powered Protocol Buffers code generation framework that provides declarative, reproducible protobuf compilation for multiple programming languages. The project eliminates dependency hell and network requirements by leveraging Nix's deterministic package management. +You maintain the big picture, create comprehensive todo lists, and delegate individual todo items to specialized subagents that work in their own context windows. -### Core Philosophy -- **Local-first**: All code generation happens locally without network dependencies -- **Reproducible**: Same inputs produce identical outputs across all environments -- **Multi-language**: Support for Go, Dart, JavaScript/TypeScript, PHP, Swift, and more -- **Developer-friendly**: Zero setup with comprehensive tooling included +## 🚨 YOUR MANDATORY WORKFLOW + +When the user gives you a project: + +### Step 1: ANALYZE & PLAN (You do this) +1. Understand the complete project scope +2. Break it down into clear, actionable todo items +3. **USE TodoWrite** to create a detailed todo list +4. Each todo should be specific enough to delegate + +### Step 2: DELEGATE TO SUBAGENTS (One todo at a time) +1. Take the FIRST todo item +2. Invoke the **`coder`** subagent with that specific task (Never trust that the `coder` agent will complete the task correctly always verify, test, and investigate changes) +3. The coder works in its OWN context window +4. Wait for coder to complete and report back + +### Step 3: TEST THE IMPLEMENTATION +1. Take the coder's completion report +2. Invoke the **`tester`** subagent to verify +3. Tester uses Playwright MCP in its OWN context window +4. Wait for test results + +### Step 4: HANDLE RESULTS +- **If tests pass**: Mark todo complete, move to next todo +- **If tests fail**: Invoke **`stuck`** agent for human input +- **If coder hits error**: They will invoke stuck agent automatically + +### Step 5: ITERATE +1. Update todo list (mark completed items) +2. Move to next todo item +3. Repeat steps 2-4 until ALL todos are complete + +## 🛠️ Available Subagents + +### coder +**Purpose**: Implement one specific todo item + +- **When to invoke**: For each coding task on your todo list +- **What to pass**: ONE specific todo item with clear requirements +- **Context**: Gets its own clean context window +- **Returns**: Implementation details and completion status +- **On error**: Will invoke stuck agent automatically + +### tester +**Purpose**: Visual verification with Playwright MCP + +- **When to invoke**: After EVERY coder completion +- **What to pass**: What was just implemented and what to verify +- **Context**: Gets its own clean context window +- **Returns**: Pass/fail with screenshots +- **On failure**: Will invoke stuck agent automatically + +### stuck +**Purpose**: Human escalation for ANY problem + +- **When to invoke**: When tests fail or you need human decision +- **What to pass**: The problem and context +- **Returns**: Human's decision on how to proceed +- **Critical**: ONLY agent that can use AskUserQuestion + +## 🚨 CRITICAL RULES FOR YOU + +**YOU (the orchestrator) MUST:** +1. ✅ Create detailed todo lists with TodoWrite +2. ✅ Delegate ONE todo at a time to coder +3. ✅ Test EVERY implementation with tester +4. ✅ Track progress and update todos +5. ✅ Maintain the big picture across 200k context +6. ✅ **ALWAYS create pages for EVERY link in headers/footers** - NO 404s allowed! + +**YOU MUST NEVER:** +1. ❌ Implement code yourself (delegate to coder) +2. ❌ Skip testing (always use tester after coder) +3. ❌ Let agents use fallbacks (enforce stuck agent) +4. ❌ Lose track of progress (maintain todo list) +5. ❌ **Put links in headers/footers without creating the actual pages** - this causes 404s! + +## 📋 Example Workflow + +``` +User: "Build a React todo app" + +YOU (Orchestrator): +1. Create todo list: + [ ] Set up React project + [ ] Create TodoList component + [ ] Create TodoItem component + [ ] Add state management + [ ] Style the app + [ ] Test all functionality + +2. Invoke coder with: "Set up React project" + → Coder works in own context, implements, reports back + +3. Invoke tester with: "Verify React app runs at localhost:3000" + → Tester uses Playwright, takes screenshots, reports success + +4. Mark first todo complete + +5. Invoke coder with: "Create TodoList component" + → Coder implements in own context + +6. Invoke tester with: "Verify TodoList renders correctly" + → Tester validates with screenshots + +... Continue until all todos done +``` + +## 🔄 The Orchestration Flow + +``` +USER gives project + ↓ +YOU analyze & create todo list (TodoWrite) + ↓ +YOU invoke coder(todo #1) + ↓ + ├─→ Error? → Coder invokes stuck → Human decides → Continue + ↓ +CODER reports completion + ↓ +YOU invoke tester(verify todo #1) + ↓ + ├─→ Fail? → Tester invokes stuck → Human decides → Continue + ↓ +TESTER reports success + ↓ +YOU mark todo #1 complete + ↓ +YOU invoke coder(todo #2) + ↓ +... Repeat until all todos done ... + ↓ +YOU report final results to USER +``` + +## 🎯 Why This Works + +**Your 200k context** = Big picture, project state, todos, progress +**Coder's fresh context** = Clean slate for implementing one task +**Tester's fresh context** = Clean slate for verifying one task +**Stuck's context** = Problem + human decision + +Each subagent gets a focused, isolated context for their specific job! + +## 💡 Key Principles + +1. **You maintain state**: Todo list, project vision, overall progress +2. **Subagents are stateless**: Each gets one task, completes it, returns +3. **One task at a time**: Don't delegate multiple tasks simultaneously +4. **Always test**: Every implementation gets verified by tester +5. **Human in the loop**: Stuck agent ensures no blind fallbacks + +## 🚀 Your First Action + +When you receive a project: + +1. **IMMEDIATELY** use TodoWrite to create comprehensive todo list +2. **IMMEDIATELY** invoke coder with first todo item +3. Wait for results, test, iterate +4. Report to user ONLY when ALL todos complete + +## ⚠️ Common Mistakes to Avoid + +❌ Implementing code yourself instead of delegating to coder +❌ Skipping the tester after coder completes +❌ Delegating multiple todos at once (do ONE at a time) +❌ Not maintaining/updating the todo list +❌ Reporting back before all todos are complete +❌ **Creating header/footer links without creating the actual pages** (causes 404s) +❌ **Not verifying all links work with tester** (always test navigation!) + +## ✅ Success Looks Like + +- Detailed todo list created immediately +- Each todo delegated to coder → tested by tester → marked complete +- Human consulted via stuck agent when problems occur +- All todos completed before final report to user +- Zero fallbacks or workarounds used +- **ALL header/footer links have actual pages created** (zero 404 errors) +- **Tester verifies ALL navigation links work** with Playwright + +--- + +**You are the conductor with perfect memory (200k context). The subagents are specialists you hire for individual tasks. Together you build amazing things!** 🚀 +Note that if you are waiting for an action to complete you should not return, you must call a Bash(sleep {best estimate of seconds to sleep until complete}). +See documents for libaries and frameworks used in .claude/contexts/ + + +Bufrnix is a Nix-powered Protocol Buffers code generation framework that provides declarative, reproducible protobuf compilation for multiple programming languages. The project eliminates dependency hell and network requirements by leveraging Nix's deterministic package management. + +- Local-first: All code generation happens locally without network dependencies +- Reproducible: Same inputs produce identical outputs across all environments +- Multi-language: Support for Go, Dart, JavaScript/TypeScript, PHP, Swift, and more +- Developer-friendly: Zero setup with comprehensive tooling included ### Quick Start 1. Install [Nix](https://nixos.org/download.html). @@ -88,23 +278,23 @@ php -S localhost:8080 -t src/ ### Core Components -1. **Language Modules (`src/languages/`)** +1. Language Modules (`src/languages/`) - Individual Nix modules for each supported language - Plugin configurations for protoc code generation - Language-specific options and package management - Examples: `go/`, `dart/`, `js/`, `php/`, `swift/` -2. **Core Library (`src/lib/`)** +2. Core Library (`src/lib/`) - `mkBufrnix.nix`: Main function for creating Bufrnix packages - `bufrnix-options.nix`: Configuration schema and validation - `utils/`: Helper functions for debugging and utilities -3. **Examples (`examples/`)** +3. Examples (`examples/`) - Complete working examples for each language - Demonstrates best practices and common patterns - Includes basic, gRPC, advanced, and multi-project scenarios -4. **Documentation (`doc/`)** +4. Documentation (`doc/`) - Astro-based documentation site - Comprehensive guides and API reference - Language-specific tutorials and troubleshooting @@ -123,13 +313,13 @@ Each language module follows a standardized, composable pattern: } ``` -**Composable Plugin System**: -- **Base module** (`default.nix`): Core protobuf message generation -- **Plugin modules** (e.g., `grpc.nix`, `validate.nix`): Feature-specific extensions -- **Framework modules** (e.g., `laravel.nix`, `symfony.nix`): Integration helpers -- **Main module**: Unified interface composing all sub-modules +Composable Plugin System: +- Base module (`default.nix`): Core protobuf message generation +- Plugin modules (e.g., `grpc.nix`, `validate.nix`): Feature-specific extensions +- Framework modules (e.g., `laravel.nix`, `symfony.nix`): Integration helpers +- Main module: Unified interface composing all sub-modules -**Example: Go Language Structure** +Example: Go Language Structure ``` src/languages/go/ ├── default.nix # Basic protoc-gen-go @@ -143,13 +333,13 @@ src/languages/go/ ### Data Flow -1. **Configuration**: User defines protobuf files and language targets in `flake.nix` -2. **Module Loading**: `mkBufrnix.nix` dynamically loads enabled language modules -3. **Validation**: Configuration is validated against the schema in `bufrnix-options.nix` -4. **Plugin Assembly**: Language modules provide protoc plugins and runtime dependencies -5. **Code Generation**: `mkBufrnix.nix` orchestrates protoc with assembled plugins -6. **Post-processing**: Language-specific hooks handle file organization and additional processing -7. **Output**: Generated code is placed in specified output directories +1. Configuration: User defines protobuf files and language targets in `flake.nix` +2. Module Loading: `mkBufrnix.nix` dynamically loads enabled language modules +3. Validation: Configuration is validated against the schema in `bufrnix-options.nix` +4. Plugin Assembly: Language modules provide protoc plugins and runtime dependencies +5. Code Generation: `mkBufrnix.nix` orchestrates protoc with assembled plugins +6. Post-processing: Language-specific hooks handle file organization and additional processing +7. Output: Generated code is placed in specified output directories ## Language Support @@ -157,17 +347,17 @@ src/languages/go/ | Language | Base Plugin | Additional Plugins | Status | |----------|-------------|-------------------|---------| -| **Go** | `protoc-gen-go` | gRPC, Connect, Gateway, Validate | ✅ Full | -| **Dart** | `protoc-gen-dart` | gRPC | ✅ Full | -| **JavaScript/TypeScript** | `protoc-gen-js` | ES modules, Connect-ES, gRPC-Web, Twirp | ✅ Full | -| **PHP** | `protoc-gen-php` | Twirp, Async, Laravel, Symfony | ✅ Full | -| **Swift** | `protoc-gen-swift` | - | ✅ Full | -| **Java** | `protoc-gen-java` | gRPC, Protovalidate | ✅ Full | -| **C/C++** | `protoc-gen-cpp` | gRPC, nanopb | ✅ Basic | -| **Kotlin** | `protoc-gen-kotlin` | gRPC, Connect | ✅ Basic | -| **C#** | `protoc-gen-csharp` | gRPC | ✅ Basic | -| **Python** | `protoc-gen-python` | gRPC, mypy, betterproto | ✅ Basic | -| **Scala** | `protoc-gen-scala` | gRPC | ✅ Basic | +| Go | `protoc-gen-go` | gRPC, Connect, Gateway, Validate | ✅ Full | +| Dart | `protoc-gen-dart` | gRPC | ✅ Full | +| JavaScript/TypeScript | `protoc-gen-js` | ES modules, Connect-ES, gRPC-Web, Twirp | ✅ Full | +| PHP | `protoc-gen-php` | Twirp, Async, Laravel, Symfony | ✅ Full | +| Swift | `protoc-gen-swift` | - | ✅ Full | +| Java | `protoc-gen-java` | gRPC, Protovalidate | ✅ Full | +| C/C++ | `protoc-gen-cpp` | gRPC, nanopb | ✅ Basic | +| Kotlin | `protoc-gen-kotlin` | gRPC, Connect | ✅ Basic | +| C# | `protoc-gen-csharp` | gRPC | ✅ Basic | +| Python | `protoc-gen-python` | gRPC, mypy, betterproto | ✅ Basic | +| Scala | `protoc-gen-scala` | gRPC | ✅ Basic | ### Adding New Language Support @@ -182,25 +372,25 @@ src/languages/go/ Bufrnix uses a comprehensive testing approach to ensure reliability across all supported languages and plugins: -1. **Nix Flake Checks (`nix flake check`)** +1. Nix Flake Checks (`nix flake check`) - Example linting to ensure consistent documentation patterns - Configuration validation and type checking - Build verification across all platforms -2. **Comprehensive Example Testing (`./test-examples.sh`)** +2. Comprehensive Example Testing (`./test-examples.sh`) - Tests 25+ different language/plugin combinations - Validates actual code generation with expected file outputs - Provides colored output with detailed error reporting - Supports verbose mode (`-v`) for debugging plugin execution - Covers: Go (6 variants), JavaScript (4 variants), Python (5 variants), PHP (2 variants), and 10+ other languages -3. **Integration Testing** +3. Integration Testing - Each example is a complete, runnable project - Real protocol definitions with services, messages, and enums - Language-specific best practices demonstration - Independent example validation for debugging specific issues -4. **Plugin Compatibility Testing** +4. Plugin Compatibility Testing - Multi-plugin scenarios (e.g., Go with gRPC + validation + gateway) - Cross-language generation consistency - Advanced plugin features (struct transformers, protovalidate, Connect-ES) @@ -283,38 +473,38 @@ debug = { ### Making Changes -1. **Language Modules**: Modify files in `src/languages/[language]/` -2. **Core Library**: Update `src/lib/mkBufrnix.nix` or option definitions -3. **Documentation**: Edit files in `doc/src/content/docs/` -4. **Examples**: Add or modify examples in `examples/` +1. Language Modules: Modify files in `src/languages/[language]/` +2. Core Library: Update `src/lib/mkBufrnix.nix` or option definitions +3. Documentation: Edit files in `doc/src/content/docs/` +4. Examples: Add or modify examples in `examples/` ### Testing Changes -1. **Test examples**: Run `./test-examples.sh` for comprehensive testing (25+ examples) -2. **Quick check**: Run `./check-examples.sh` for faster validation -3. **Test specific language**: Navigate to relevant example and run `nix run` -4. **Test documentation**: Build docs with `cd doc && bun run build` -5. **Lint code**: Run `nix fmt` and `lint` commands -6. **Nix flake checks**: Run `nix flake check` to validate all checks +1. Test examples: Run `./test-examples.sh` for comprehensive testing (25+ examples) +2. Quick check: Run `./check-examples.sh` for faster validation +3. Test specific language: Navigate to relevant example and run `nix run` +4. Test documentation: Build docs with `cd doc && bun run build` +5. Lint code: Run `nix fmt` and `lint` commands +6. Nix flake checks: Run `nix flake check` to validate all checks ### Adding New Features -1. **Plugin Support**: Add new plugin configurations to language modules -2. **Language Support**: Follow the language addition process above -3. **Configuration Options**: Update `bufrnix-options.nix` with new options -4. **Documentation**: Update relevant docs and add examples +1. Plugin Support: Add new plugin configurations to language modules +2. Language Support: Follow the language addition process above +3. Configuration Options: Update `bufrnix-options.nix` with new options +4. Documentation: Update relevant docs and add examples ## File Organization ### Important Files -- **`flake.nix`**: Main Nix flake definition with package exports -- **`src/lib/mkBufrnix.nix`**: Core Bufrnix package creation function -- **`src/lib/bufrnix-options.nix`**: Configuration schema and validation -- **`src/languages/*/default.nix`**: Language-specific implementations -- **`check-examples.sh`**: Quick validation script for CI/CD -- **`test-examples.sh`**: Comprehensive test suite covering 25+ language examples -- **`lint-examples.sh`**: Ensures example flake.nix files have proper documentation +- `flake.nix`: Main Nix flake definition with package exports +- `src/lib/mkBufrnix.nix`: Core Bufrnix package creation function +- `src/lib/bufrnix-options.nix`: Configuration schema and validation +- `src/languages/*/default.nix`: Language-specific implementations +- `check-examples.sh`: Quick validation script for CI/CD +- `test-examples.sh`: Comprehensive test suite covering 25+ language examples +- `lint-examples.sh`: Ensures example flake.nix files have proper documentation ### Directory Structure Patterns @@ -336,10 +526,10 @@ src/languages/[language]/ ### Common Issues -1. **Missing Dependencies**: Ensure Nix flakes are enabled and all inputs are properly defined -2. **Generation Failures**: Check `debug.enable = true` for detailed error output -3. **Plugin Errors**: Verify plugin compatibility with your protobuf schema -4. **Path Issues**: Ensure `sourceDirectories` and `includeDirectories` are correct +1. Missing Dependencies: Ensure Nix flakes are enabled and all inputs are properly defined +2. Generation Failures: Check `debug.enable = true` for detailed error output +3. Plugin Errors: Verify plugin compatibility with your protobuf schema +4. Path Issues: Ensure `sourceDirectories` and `includeDirectories` are correct ### Debug Configuration @@ -418,6 +608,466 @@ config = { }; ``` -This project emphasizes **reproducibility**, **developer experience**, and **local-first development** while maintaining compatibility with the broader Protocol Buffers ecosystem. +This project emphasizes reproducibility, developer experience, and local-first development while maintaining compatibility with the broader Protocol Buffers ecosystem. For full guides and examples visit . + + +# Spectr Instructions + +Instructions for AI coding assistants using Spectr for spec-driven development. + +## TL;DR Quick Checklist + +- Search existing work: `spectr spec list --long`, `spectr list` (use `rg` only for full-text search) +- Decide scope: new capability vs modify existing capability +- Pick a unique `change-id`: kebab-case, verb-led (`add-`, `update-`, `remove-`, `refactor-`) +- Scaffold: `proposal.md`, `tasks.md`, `design.md` (only if needed), and delta specs per affected capability +- Write deltas: use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements`; include at least one `#### Scenario:` per requirement +- Validate: `spectr validate [change-id] --strict` and fix issues +- Request approval: Do not start implementation until proposal is approved + +## Three-Stage Workflow + +### Stage 1: Creating Changes +Create proposal when you need to: +- Add features or functionality +- Make breaking changes (API, schema) +- Change architecture or patterns +- Optimize performance (changes behavior) +- Update security patterns + +Triggers (examples): +- "Help me create a change proposal" +- "Help me plan a change" +- "Help me create a proposal" +- "I want to create a spec proposal" +- "I want to create a spec" + +Loose matching guidance: +- Contains one of: `proposal`, `change`, `spec` +- With one of: `create`, `plan`, `make`, `start`, `help` + +Skip proposal for: +- Bug fixes (restore intended behavior) +- Typos, formatting, comments +- Dependency updates (non-breaking) +- Configuration changes +- Tests for existing behavior + +**Workflow** +1. Review `spectr/project.md`, `spectr list`, and `spectr list --specs` to understand current context. +2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, optional `design.md`, and spec deltas under `spectr/changes//`. +3. Draft spec deltas using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement. +4. Run `spectr validate --strict` and resolve any issues before sharing the proposal. + +### Stage 2: Implementing Changes +Track these steps as TODOs and complete them one by one. +1. **Read proposal.md** - Understand what's being built +2. **Read design.md** (if exists) - Review technical decisions +3. **Read tasks.md** - Get implementation checklist +4. **Implement tasks sequentially** - Complete in order +5. **Confirm completion** - Ensure every item in `tasks.md` is finished before updating statuses +6. **Update checklist** - After all work is done, set every task to `- [x]` so the list reflects reality +7. **Approval gate** - Do not start implementation until the proposal is reviewed and approved + +### Stage 3: Archiving Changes +After deployment, create separate PR to: +- Move `changes/[name]/` → `changes/archive/YYYY-MM-DD-[name]/` +- Update `specs/` if capabilities changed +- Use `spectr archive --skip-specs --yes` for tooling-only changes (always pass the change ID explicitly) +- Run `spectr validate --strict` to confirm the archived change passes checks + +## Before Any Task + +**Context Checklist:** +- [ ] Read relevant specs in `specs/[capability]/spec.md` +- [ ] Check pending changes in `changes/` for conflicts +- [ ] Read `spectr/project.md` for conventions +- [ ] Run `spectr list` to see active changes +- [ ] Run `spectr list --specs` to see existing capabilities + +**Before Creating Specs:** +- Always check if capability already exists +- Prefer modifying existing specs over creating duplicates +- Use `spectr show [spec]` to review current state +- If request is ambiguous, ask 1–2 clarifying questions before scaffolding + +### Search Guidance +- Enumerate specs: `spectr spec list --long` (or `--json` for scripts) +- Enumerate changes: `spectr list` (or `spectr change list --json` - deprecated but available) +- Show details: + - Spec: `spectr show --type spec` (use `--json` for filters) + - Change: `spectr show --json --deltas-only` +- Full-text search (use ripgrep): `rg -n "Requirement:|Scenario:" spectr/specs` + +## Quick Start + +### CLI Commands + +```bash +# Essential commands +spectr list # List active changes +spectr list --specs # List specifications +spectr show [item] # Display change or spec +spectr validate [item] # Validate changes or specs +spectr archive [--yes|-y] # Archive after deployment (add --yes for non-interactive runs) + +# Project management +spectr init [path] # Initialize Spectr +spectr update [path] # Update instruction files + +# Interactive mode +spectr show # Prompts for selection +spectr validate # Bulk validation mode + +# Debugging +spectr show [change] --json --deltas-only +spectr validate [change] --strict +``` + +### Command Flags + +- `--json` - Machine-readable output +- `--type change|spec` - Disambiguate items +- `--strict` - Comprehensive validation +- `--no-interactive` - Disable prompts +- `--skip-specs` - Archive without spec updates +- `--yes`/`-y` - Skip confirmation prompts (non-interactive archive) + +## Directory Structure + +``` +spectr/ +├── project.md # Project conventions +├── specs/ # Current truth - what IS built +│ └── [capability]/ # Single focused capability +│ ├── spec.md # Requirements and scenarios +│ └── design.md # Technical patterns +├── changes/ # Proposals - what SHOULD change +│ ├── [change-name]/ +│ │ ├── proposal.md # Why, what, impact +│ │ ├── tasks.md # Implementation checklist +│ │ ├── design.md # Technical decisions (optional; see criteria) +│ │ └── specs/ # Delta changes +│ │ └── [capability]/ +│ │ └── spec.md # ADDED/MODIFIED/REMOVED +│ └── archive/ # Completed changes +``` + +## Creating Change Proposals + +### Decision Tree + +``` +New request? +├─ Bug fix restoring spec behavior? → Fix directly +├─ Typo/format/comment? → Fix directly +├─ New feature/capability? → Create proposal +├─ Breaking change? → Create proposal +├─ Architecture change? → Create proposal +└─ Unclear? → Create proposal (safer) +``` + +### Proposal Structure + +1. **Create directory:** `changes/[change-id]/` (kebab-case, verb-led, unique) + +2. **Write proposal.md:** +```markdown +# Change: [Brief description of change] + +## Why +[1-2 sentences on problem/opportunity] + +## What Changes +- [Bullet list of changes] +- [Mark breaking changes with **BREAKING**] + +## Impact +- Affected specs: [list capabilities] +- Affected code: [key files/systems] +``` + +3. **Create spec deltas:** `specs/[capability]/spec.md` +```markdown +## ADDED Requirements +### Requirement: New Feature +The system SHALL provide... + +#### Scenario: Success case +- **WHEN** user performs action +- **THEN** expected result + +## MODIFIED Requirements +### Requirement: Existing Feature +[Complete modified requirement] + +## REMOVED Requirements +### Requirement: Old Feature +**Reason**: [Why removing] +**Migration**: [How to handle] +``` +If multiple capabilities are affected, create multiple delta files under `changes/[change-id]/specs//spec.md`—one per capability. + +4. **Create tasks.md:** +```markdown +## 1. Implementation +- [ ] 1.1 Create database schema +- [ ] 1.2 Implement API endpoint +- [ ] 1.3 Add frontend component +- [ ] 1.4 Write tests +``` + +5. **Create design.md when needed:** +Create `design.md` if any of the following apply; otherwise omit it: +- Cross-cutting change (multiple services/modules) or a new architectural pattern +- New external dependency or significant data model changes +- Security, performance, or migration complexity +- Ambiguity that benefits from technical decisions before coding + +Minimal `design.md` skeleton: +```markdown +## Context +[Background, constraints, stakeholders] + +## Goals / Non-Goals +- Goals: [...] +- Non-Goals: [...] + +## Decisions +- Decision: [What and why] +- Alternatives considered: [Options + rationale] + +## Risks / Trade-offs +- [Risk] → Mitigation + +## Migration Plan +[Steps, rollback] + +## Open Questions +- [...] +``` + +## Spec File Format + +### Critical: Scenario Formatting + +**CORRECT** (use #### headers): +```markdown +#### Scenario: User login success +- **WHEN** valid credentials provided +- **THEN** return JWT token +``` + +**WRONG** (don't use bullets or bold): +```markdown +- **Scenario: User login** ❌ +**Scenario**: User login ❌ +### Scenario: User login ❌ +``` + +Every requirement MUST have at least one scenario. + +### Requirement Wording +- Use SHALL/MUST for normative requirements (avoid should/may unless intentionally non-normative) + +### Delta Operations + +- `## ADDED Requirements` - New capabilities +- `## MODIFIED Requirements` - Changed behavior +- `## REMOVED Requirements` - Deprecated features +- `## RENAMED Requirements` - Name changes + +Headers matched with `trim(header)` - whitespace ignored. + +#### When to use ADDED vs MODIFIED +- ADDED: Introduces a new capability or sub-capability that can stand alone as a requirement. Prefer ADDED when the change is orthogonal (e.g., adding "Slash Command Configuration") rather than altering the semantics of an existing requirement. +- MODIFIED: Changes the behavior, scope, or acceptance criteria of an existing requirement. Always paste the full, updated requirement content (header + all scenarios). The archiver will replace the entire requirement with what you provide here; partial deltas will drop previous details. +- RENAMED: Use when only the name changes. If you also change behavior, use RENAMED (name) plus MODIFIED (content) referencing the new name. + +Common pitfall: Using MODIFIED to add a new concern without including the previous text. This causes loss of detail at archive time. If you aren't explicitly changing the existing requirement, add a new requirement under ADDED instead. + +Authoring a MODIFIED requirement correctly: +1) Locate the existing requirement in `spectr/specs//spec.md`. +2) Copy the entire requirement block (from `### Requirement: ...` through its scenarios). +3) Paste it under `## MODIFIED Requirements` and edit to reflect the new behavior. +4) Ensure the header text matches exactly (whitespace-insensitive) and keep at least one `#### Scenario:`. + +Example for RENAMED: +```markdown +## RENAMED Requirements +- FROM: `### Requirement: Login` +- TO: `### Requirement: User Authentication` +``` + +## Troubleshooting + +### Common Errors + +**"Change must have at least one delta"** +- Check `changes/[name]/specs/` exists with .md files +- Verify files have operation prefixes (## ADDED Requirements) + +**"Requirement must have at least one scenario"** +- Check scenarios use `#### Scenario:` format (4 hashtags) +- Don't use bullet points or bold for scenario headers + +**Silent scenario parsing failures** +- Exact format required: `#### Scenario: Name` +- Debug with: `spectr show [change] --json --deltas-only` + +### Validation Tips + +```bash +# Always use strict mode for comprehensive checks +spectr validate [change] --strict + +# Debug delta parsing +spectr show [change] --json | jq '.deltas' + +# Check specific requirement +spectr show [spec] --json -r 1 +``` + +## Happy Path Script + +```bash +# 1) Explore current state +spectr spec list --long +spectr list +# Optional full-text search: +# rg -n "Requirement:|Scenario:" spectr/specs +# rg -n "^#|Requirement:" spectr/changes + +# 2) Choose change id and scaffold +CHANGE=add-two-factor-auth +mkdir -p spectr/changes/$CHANGE/{specs/auth} +printf "## Why\\n...\\n\\n## What Changes\\n- ...\\n\\n## Impact\\n- ...\\n" > spectr/changes/$CHANGE/proposal.md +printf "## 1. Implementation\\n- [ ] 1.1 ...\\n" > spectr/changes/$CHANGE/tasks.md + +# 3) Add deltas (example) +cat > spectr/changes/$CHANGE/specs/auth/spec.md << 'EOF' +## ADDED Requirements +### Requirement: Two-Factor Authentication +Users MUST provide a second factor during login. + +#### Scenario: OTP required +- **WHEN** valid credentials are provided +- **THEN** an OTP challenge is required +EOF + +# 4) Validate +spectr validate $CHANGE --strict +``` + +## Multi-Capability Example + +``` +spectr/changes/add-2fa-notify/ +├── proposal.md +├── tasks.md +└── specs/ + ├── auth/ + │ └── spec.md # ADDED: Two-Factor Authentication + └── notifications/ + └── spec.md # ADDED: OTP email notification +``` + +auth/spec.md +```markdown +## ADDED Requirements +### Requirement: Two-Factor Authentication +... +``` + +notifications/spec.md +```markdown +## ADDED Requirements +### Requirement: OTP Email Notification +... +``` + +## Best Practices + +### Simplicity First +- Default to <100 lines of new code +- Single-file implementations until proven insufficient +- Avoid frameworks without clear justification +- Choose boring, proven patterns + +### Complexity Triggers +Only add complexity with: +- Performance data showing current solution too slow +- Concrete scale requirements (>1000 users, >100MB data) +- Multiple proven use cases requiring abstraction + +### Clear References +- Use `file.ts:42` format for code locations +- Reference specs as `specs/auth/spec.md` +- Link related changes and PRs + +### Capability Naming +- Use verb-noun: `user-auth`, `payment-capture` +- Single purpose per capability +- 10-minute understandability rule +- Split if description needs "AND" + +### Change ID Naming +- Use kebab-case, short and descriptive: `add-two-factor-auth` +- Prefer verb-led prefixes: `add-`, `update-`, `remove-`, `refactor-` +- Ensure uniqueness; if taken, append `-2`, `-3`, etc. + +## Tool Selection Guide + +| Task | Tool | Why | +|------|------|-----| +| Find files by pattern | Glob | Fast pattern matching | +| Search code content | Grep | Optimized regex search | +| Read specific files | Read | Direct file access | +| Explore unknown scope | Task | Multi-step investigation | + +## Error Recovery + +### Change Conflicts +1. Run `spectr list` to see active changes +2. Check for overlapping specs +3. Coordinate with change owners +4. Consider combining proposals + +### Validation Failures +1. Run with `--strict` flag +2. Check JSON output for details +3. Verify spec file format +4. Ensure scenarios properly formatted + +### Missing Context +1. Read project.md first +2. Check related specs +3. Review recent archives +4. Ask for clarification + +## Quick Reference + +### Stage Indicators +- `changes/` - Proposed, not yet built +- `specs/` - Built and deployed +- `archive/` - Completed changes + +### File Purposes +- `proposal.md` - Why and what +- `tasks.md` - Implementation steps +- `design.md` - Technical decisions +- `spec.md` - Requirements and behavior + +### CLI Essentials +```bash +spectr list # What's in progress? +spectr show [item] # View details +spectr validate --strict # Is it correct? +spectr archive [--yes|-y] # Mark complete (add --yes for automation) +``` + +Remember: Specs are truth. Changes are proposals. Keep them in sync. + + diff --git a/spectr/AGENTS.md b/spectr/AGENTS.md new file mode 100644 index 0000000..355969d --- /dev/null +++ b/spectr/AGENTS.md @@ -0,0 +1,454 @@ +# OpenSpec Instructions + +Instructions for AI coding assistants using OpenSpec for spec-driven development. + +## TL;DR Quick Checklist + +- Search existing work: `openspec spec list --long`, `openspec list` (use `rg` only for full-text search) +- Decide scope: new capability vs modify existing capability +- Pick a unique `change-id`: kebab-case, verb-led (`add-`, `update-`, `remove-`, `refactor-`) +- Scaffold: `proposal.md`, `tasks.md`, `design.md` (only if needed), and delta specs per affected capability +- Write deltas: use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements`; include at least one `#### Scenario:` per requirement +- Validate: `openspec validate [change-id] --strict` and fix issues +- Request approval: Do not start implementation until proposal is approved + +## Three-Stage Workflow + +### Stage 1: Creating Changes +Create proposal when you need to: +- Add features or functionality +- Make breaking changes (API, schema) +- Change architecture or patterns +- Optimize performance (changes behavior) +- Update security patterns + +Triggers (examples): +- "Help me create a change proposal" +- "Help me plan a change" +- "Help me create a proposal" +- "I want to create a spec proposal" +- "I want to create a spec" + +Loose matching guidance: +- Contains one of: `proposal`, `change`, `spec` +- With one of: `create`, `plan`, `make`, `start`, `help` + +Skip proposal for: +- Bug fixes (restore intended behavior) +- Typos, formatting, comments +- Dependency updates (non-breaking) +- Configuration changes +- Tests for existing behavior + +**Workflow** +1. Review `openspec/project.md`, `openspec list`, and `openspec list --specs` to understand current context. +2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, optional `design.md`, and spec deltas under `openspec/changes//`. +3. Draft spec deltas using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement. +4. Run `openspec validate --strict` and resolve any issues before sharing the proposal. + +### Stage 2: Implementing Changes +Track these steps as TODOs and complete them one by one. +1. **Read proposal.md** - Understand what's being built +2. **Read design.md** (if exists) - Review technical decisions +3. **Read tasks.md** - Get implementation checklist +4. **Implement tasks sequentially** - Complete in order +5. **Confirm completion** - Ensure every item in `tasks.md` is finished before updating statuses +6. **Update checklist** - After all work is done, set every task to `- [x]` so the list reflects reality +7. **Approval gate** - Do not start implementation until the proposal is reviewed and approved + +### Stage 3: Archiving Changes +After deployment, create separate PR to: +- Move `changes/[name]/` → `changes/archive/YYYY-MM-DD-[name]/` +- Update `specs/` if capabilities changed +- Use `openspec archive --skip-specs --yes` for tooling-only changes (always pass the change ID explicitly) +- Run `openspec validate --strict` to confirm the archived change passes checks + +## Before Any Task + +**Context Checklist:** +- [ ] Read relevant specs in `specs/[capability]/spec.md` +- [ ] Check pending changes in `changes/` for conflicts +- [ ] Read `openspec/project.md` for conventions +- [ ] Run `openspec list` to see active changes +- [ ] Run `openspec list --specs` to see existing capabilities + +**Before Creating Specs:** +- Always check if capability already exists +- Prefer modifying existing specs over creating duplicates +- Use `openspec show [spec]` to review current state +- If request is ambiguous, ask 1–2 clarifying questions before scaffolding + +### Search Guidance +- Enumerate specs: `openspec spec list --long` (or `--json` for scripts) +- Enumerate changes: `openspec list` (or `openspec change list --json` - deprecated but available) +- Show details: + - Spec: `openspec show --type spec` (use `--json` for filters) + - Change: `openspec show --json --deltas-only` +- Full-text search (use ripgrep): `rg -n "Requirement:|Scenario:" openspec/specs` + +## Quick Start + +### CLI Commands + +```bash +# Essential commands +openspec list # List active changes +openspec list --specs # List specifications +openspec show [item] # Display change or spec +openspec validate [item] # Validate changes or specs +openspec archive [--yes|-y] # Archive after deployment (add --yes for non-interactive runs) + +# Project management +openspec init [path] # Initialize OpenSpec +openspec update [path] # Update instruction files + +# Interactive mode +openspec show # Prompts for selection +openspec validate # Bulk validation mode + +# Debugging +openspec show [change] --json --deltas-only +openspec validate [change] --strict +``` + +### Command Flags + +- `--json` - Machine-readable output +- `--type change|spec` - Disambiguate items +- `--strict` - Comprehensive validation +- `--no-interactive` - Disable prompts +- `--skip-specs` - Archive without spec updates +- `--yes`/`-y` - Skip confirmation prompts (non-interactive archive) + +## Directory Structure + +``` +openspec/ +├── project.md # Project conventions +├── specs/ # Current truth - what IS built +│ └── [capability]/ # Single focused capability +│ ├── spec.md # Requirements and scenarios +│ └── design.md # Technical patterns +├── changes/ # Proposals - what SHOULD change +│ ├── [change-name]/ +│ │ ├── proposal.md # Why, what, impact +│ │ ├── tasks.md # Implementation checklist +│ │ ├── design.md # Technical decisions (optional; see criteria) +│ │ └── specs/ # Delta changes +│ │ └── [capability]/ +│ │ └── spec.md # ADDED/MODIFIED/REMOVED +│ └── archive/ # Completed changes +``` + +## Creating Change Proposals + +### Decision Tree + +``` +New request? +├─ Bug fix restoring spec behavior? → Fix directly +├─ Typo/format/comment? → Fix directly +├─ New feature/capability? → Create proposal +├─ Breaking change? → Create proposal +├─ Architecture change? → Create proposal +└─ Unclear? → Create proposal (safer) +``` + +### Proposal Structure + +1. **Create directory:** `changes/[change-id]/` (kebab-case, verb-led, unique) + +2. **Write proposal.md:** +```markdown +## Why +[1-2 sentences on problem/opportunity] + +## What Changes +- [Bullet list of changes] +- [Mark breaking changes with **BREAKING**] + +## Impact +- Affected specs: [list capabilities] +- Affected code: [key files/systems] +``` + +3. **Create spec deltas:** `specs/[capability]/spec.md` +```markdown +## ADDED Requirements +### Requirement: New Feature +The system SHALL provide... + +#### Scenario: Success case +- **WHEN** user performs action +- **THEN** expected result + +## MODIFIED Requirements +### Requirement: Existing Feature +[Complete modified requirement] + +## REMOVED Requirements +### Requirement: Old Feature +**Reason**: [Why removing] +**Migration**: [How to handle] +``` +If multiple capabilities are affected, create multiple delta files under `changes/[change-id]/specs//spec.md`—one per capability. + +4. **Create tasks.md:** +```markdown +## 1. Implementation +- [ ] 1.1 Create database schema +- [ ] 1.2 Implement API endpoint +- [ ] 1.3 Add frontend component +- [ ] 1.4 Write tests +``` + +5. **Create design.md when needed:** +Create `design.md` if any of the following apply; otherwise omit it: +- Cross-cutting change (multiple services/modules) or a new architectural pattern +- New external dependency or significant data model changes +- Security, performance, or migration complexity +- Ambiguity that benefits from technical decisions before coding + +Minimal `design.md` skeleton: +```markdown +## Context +[Background, constraints, stakeholders] + +## Goals / Non-Goals +- Goals: [...] +- Non-Goals: [...] + +## Decisions +- Decision: [What and why] +- Alternatives considered: [Options + rationale] + +## Risks / Trade-offs +- [Risk] → Mitigation + +## Migration Plan +[Steps, rollback] + +## Open Questions +- [...] +``` + +## Spec File Format + +### Critical: Scenario Formatting + +**CORRECT** (use #### headers): +```markdown +#### Scenario: User login success +- **WHEN** valid credentials provided +- **THEN** return JWT token +``` + +**WRONG** (don't use bullets or bold): +```markdown +- **Scenario: User login** ❌ +**Scenario**: User login ❌ +### Scenario: User login ❌ +``` + +Every requirement MUST have at least one scenario. + +### Requirement Wording +- Use SHALL/MUST for normative requirements (avoid should/may unless intentionally non-normative) + +### Delta Operations + +- `## ADDED Requirements` - New capabilities +- `## MODIFIED Requirements` - Changed behavior +- `## REMOVED Requirements` - Deprecated features +- `## RENAMED Requirements` - Name changes + +Headers matched with `trim(header)` - whitespace ignored. + +#### When to use ADDED vs MODIFIED +- ADDED: Introduces a new capability or sub-capability that can stand alone as a requirement. Prefer ADDED when the change is orthogonal (e.g., adding "Slash Command Configuration") rather than altering the semantics of an existing requirement. +- MODIFIED: Changes the behavior, scope, or acceptance criteria of an existing requirement. Always paste the full, updated requirement content (header + all scenarios). The archiver will replace the entire requirement with what you provide here; partial deltas will drop previous details. +- RENAMED: Use when only the name changes. If you also change behavior, use RENAMED (name) plus MODIFIED (content) referencing the new name. + +Common pitfall: Using MODIFIED to add a new concern without including the previous text. This causes loss of detail at archive time. If you aren’t explicitly changing the existing requirement, add a new requirement under ADDED instead. + +Authoring a MODIFIED requirement correctly: +1) Locate the existing requirement in `openspec/specs//spec.md`. +2) Copy the entire requirement block (from `### Requirement: ...` through its scenarios). +3) Paste it under `## MODIFIED Requirements` and edit to reflect the new behavior. +4) Ensure the header text matches exactly (whitespace-insensitive) and keep at least one `#### Scenario:`. + +Example for RENAMED: +```markdown +## RENAMED Requirements +- FROM: `### Requirement: Login` +- TO: `### Requirement: User Authentication` +``` + +## Troubleshooting + +### Common Errors + +**"Change must have at least one delta"** +- Check `changes/[name]/specs/` exists with .md files +- Verify files have operation prefixes (## ADDED Requirements) + +**"Requirement must have at least one scenario"** +- Check scenarios use `#### Scenario:` format (4 hashtags) +- Don't use bullet points or bold for scenario headers + +**Silent scenario parsing failures** +- Exact format required: `#### Scenario: Name` +- Debug with: `openspec show [change] --json --deltas-only` + +### Validation Tips + +```bash +# Always use strict mode for comprehensive checks +openspec validate [change] --strict + +# Debug delta parsing +openspec show [change] --json | jq '.deltas' + +# Check specific requirement +openspec show [spec] --json -r 1 +``` + +## Happy Path Script + +```bash +# 1) Explore current state +openspec spec list --long +openspec list +# Optional full-text search: +# rg -n "Requirement:|Scenario:" openspec/specs +# rg -n "^#|Requirement:" openspec/changes + +# 2) Choose change id and scaffold +CHANGE=add-two-factor-auth +mkdir -p openspec/changes/$CHANGE/{specs/auth} +printf "## Why\n...\n\n## What Changes\n- ...\n\n## Impact\n- ...\n" > openspec/changes/$CHANGE/proposal.md +printf "## 1. Implementation\n- [ ] 1.1 ...\n" > openspec/changes/$CHANGE/tasks.md + +# 3) Add deltas (example) +cat > openspec/changes/$CHANGE/specs/auth/spec.md << 'EOF' +## ADDED Requirements +### Requirement: Two-Factor Authentication +Users MUST provide a second factor during login. + +#### Scenario: OTP required +- **WHEN** valid credentials are provided +- **THEN** an OTP challenge is required +EOF + +# 4) Validate +openspec validate $CHANGE --strict +``` + +## Multi-Capability Example + +``` +openspec/changes/add-2fa-notify/ +├── proposal.md +├── tasks.md +└── specs/ + ├── auth/ + │ └── spec.md # ADDED: Two-Factor Authentication + └── notifications/ + └── spec.md # ADDED: OTP email notification +``` + +auth/spec.md +```markdown +## ADDED Requirements +### Requirement: Two-Factor Authentication +... +``` + +notifications/spec.md +```markdown +## ADDED Requirements +### Requirement: OTP Email Notification +... +``` + +## Best Practices + +### Simplicity First +- Default to <100 lines of new code +- Single-file implementations until proven insufficient +- Avoid frameworks without clear justification +- Choose boring, proven patterns + +### Complexity Triggers +Only add complexity with: +- Performance data showing current solution too slow +- Concrete scale requirements (>1000 users, >100MB data) +- Multiple proven use cases requiring abstraction + +### Clear References +- Use `file.ts:42` format for code locations +- Reference specs as `specs/auth/spec.md` +- Link related changes and PRs + +### Capability Naming +- Use verb-noun: `user-auth`, `payment-capture` +- Single purpose per capability +- 10-minute understandability rule +- Split if description needs "AND" + +### Change ID Naming +- Use kebab-case, short and descriptive: `add-two-factor-auth` +- Prefer verb-led prefixes: `add-`, `update-`, `remove-`, `refactor-` +- Ensure uniqueness; if taken, append `-2`, `-3`, etc. + +## Tool Selection Guide + +| Task | Tool | Why | +|------|------|-----| +| Find files by pattern | Glob | Fast pattern matching | +| Search code content | Grep | Optimized regex search | +| Read specific files | Read | Direct file access | +| Explore unknown scope | Task | Multi-step investigation | + +## Error Recovery + +### Change Conflicts +1. Run `openspec list` to see active changes +2. Check for overlapping specs +3. Coordinate with change owners +4. Consider combining proposals + +### Validation Failures +1. Run with `--strict` flag +2. Check JSON output for details +3. Verify spec file format +4. Ensure scenarios properly formatted + +### Missing Context +1. Read project.md first +2. Check related specs +3. Review recent archives +4. Ask for clarification + +## Quick Reference + +### Stage Indicators +- `changes/` - Proposed, not yet built +- `specs/` - Built and deployed +- `archive/` - Completed changes + +### File Purposes +- `proposal.md` - Why and what +- `tasks.md` - Implementation steps +- `design.md` - Technical decisions +- `spec.md` - Requirements and behavior + +### CLI Essentials +```bash +openspec list # What's in progress? +openspec show [item] # View details +openspec validate --strict # Is it correct? +openspec archive [--yes|-y] # Mark complete (add --yes for automation) +``` + +Remember: Specs are truth. Changes are proposals. Keep them in sync. diff --git a/spectr/changes/remove-es-generatepackagejson/design.md b/spectr/changes/remove-es-generatepackagejson/design.md new file mode 100644 index 0000000..5fb7f88 --- /dev/null +++ b/spectr/changes/remove-es-generatepackagejson/design.md @@ -0,0 +1,258 @@ +# Design Document: Remove generatePackageJson Feature + +## Overview + +This document outlines the architectural reasoning for completely removing the `generatePackageJson` feature from Bufrnix's JavaScript/TypeScript language modules. + +## Current Architecture + +### Package.json Generation Locations + +**1. ES Modules (default.nix)** +```nix +${optionalString (cfg.es.enable && cfg.es.generatePackageJson) (let + esOutputPath = ... +in '' + cat > ${esOutputPath}/package.json < ${outputPath}/package.json < ${esOutputPath}/package.json < ${outputPath}/package.json < "${cfg.outputPath}/build.gradle.kts" < build.gradle.kts` template generation + - Remove `cat > settings.gradle.kts` template generation + +3. **Examples**: + - `examples/kotlin-basic/flake.nix`: Remove `generateBuildFile = true;` configuration + - `examples/kotlin-grpc/flake.nix`: Remove `generateBuildFile = true;` configuration + +4. **Documentation**: + - `doc/src/content/docs/reference/languages/kotlin.x-basic-configuration.nix`: Update example configuration + - `examples/kotlin-basic/README.md`: Update documentation reference if present + +## Rationale + +### Why Remove This Feature + +1. **Limited Usage**: The automatic build file generation is rarely used by practitioners who prefer explicit control +2. **Maintenance Burden**: Requires keeping Gradle template syntax current across Kotlin/Gradle versions +3. **Design Clarity**: Bufrnix's core responsibility is protobuf code generation, not build system management +4. **Consistency**: Users already manage their project structure; auto-generation creates inconsistency +5. **Simplification**: Reduces configuration options and module complexity + +### Why This Change Is Safe + +1. **Backward-Compatible Alternative**: Users can easily create their own `build.gradle.kts` files +2. **No Generated Code Loss**: Proto files are still generated; only build template generation is removed +3. **Clear Migration Path**: Examples can document manual build file setup instead +4. **Isolated Impact**: Only affects Kotlin; doesn't impact other languages (Scala retains its option by choice) + +## Detailed Changes + +### 1. Configuration Schema Change + +**File**: `src/lib/bufrnix-options.nix` + +Remove the `generateBuildFile` mkOption definition from the `kotlin` configuration section. + +### 2. Kotlin Module Simplification + +**File**: `src/languages/kotlin/default.nix` + +Simplify the `initHooks` section by removing all conditional blocks guarded by `optionalString cfg.generateBuildFile`. + +**Before**: 83 lines of template-based build file generation +**After**: Minimal initialization hook focused only on creating output directories + +### 3. Example Updates + +**Files**: +- `examples/kotlin-basic/flake.nix` +- `examples/kotlin-grpc/flake.nix` + +Remove the `generateBuildFile = true;` line from each Kotlin example configuration. + +### 4. Documentation Updates + +**Files**: +- `doc/src/content/docs/reference/languages/kotlin.x-basic-configuration.nix` +- Update any README references + +Update code examples and configuration snippets to remove `generateBuildFile` references. + +## Dependencies and Constraints + +- **No external dependencies**: This is a purely internal change +- **No breaking changes for users who don't use generateBuildFile**: Unaffected +- **Minimal migration for users using generateBuildFile**: Simply remove the option and provide custom build files + +## Validation Plan + +1. **Schema Validation**: Run `openspec validate remove-kotlin-generateBuildFile --strict` +2. **Example Validation**: Run `./check-examples.sh` to ensure Kotlin examples still work +3. **Comprehensive Testing**: Run `./test-examples.sh` to validate all Kotlin variants +4. **Manual Testing**: Verify that Kotlin examples generate code correctly without build files + +## Related Changes + +- **Not affected**: Scala module retains its `generateBuildFile` option (different design decision) +- **Not affected**: Other language modules (no similar feature) + +## Future Considerations + +- Users needing auto-generated build files can create wrapper tools or Nix functions +- Build file generation could be added as an optional post-generation hook in the future if demand warrants +- This sets precedent for removing rarely-used configuration complexity + +## Questions for Stakeholders + +1. Are there known users relying on the `generateBuildFile` option? +2. Should we provide migration documentation for existing users? +3. Would a deprecation period be beneficial before removal? + +## Notes + +- This proposal focuses solely on Kotlin's `generateBuildFile` option +- Scala's `generateBuildFile` is retained because it serves a different role in that ecosystem +- The change aligns Bufrnix with its core responsibility: protocol buffer code generation diff --git a/spectr/changes/remove-kotlin-generateBuildFile/specs/kotlin-build-file-removal/spec.md b/spectr/changes/remove-kotlin-generateBuildFile/specs/kotlin-build-file-removal/spec.md new file mode 100644 index 0000000..7352fa6 --- /dev/null +++ b/spectr/changes/remove-kotlin-generateBuildFile/specs/kotlin-build-file-removal/spec.md @@ -0,0 +1,265 @@ +# Specification: Remove Kotlin Build File Generation + +**Capability**: Remove automatic `build.gradle.kts` generation from Kotlin language module + +**Status**: Proposed + +## Overview + +This specification defines the removal of the `generateBuildFile` configuration option and all related build file generation logic from the Kotlin language module in Bufrnix. + +## Current Behavior + +### What Currently Exists + +1. **Configuration Option**: `languages.kotlin.generateBuildFile` (boolean, default: true) +2. **Generated Files**: + - `build.gradle.kts` (Gradle build file with Kotlin configuration) + - `settings.gradle.kts` (Gradle settings file) +3. **Features**: + - Automatic inclusion of protobuf-gradle plugin configuration + - Conditional inclusion of gRPC plugin configuration + - Conditional inclusion of Connect RPC plugin configuration + - Management of Kotlin and Protobuf dependency versions + +### Code Locations + +- **Schema Definition**: `src/lib/bufrnix-options.nix:2139-2143` +- **Implementation**: `src/languages/kotlin/default.nix:80-154` +- **Examples Using Feature**: + - `examples/kotlin-basic/flake.nix` + - `examples/kotlin-grpc/flake.nix` + +## Desired Behavior + +### REMOVED Requirements + +#### Requirement: Automatic Build File Generation +The system shall **NOT** automatically generate `build.gradle.kts` files during Kotlin code generation. + +**Rationale**: +- Build file management is outside Bufrnix's core responsibility (protocol buffer code generation) +- Users prefer explicit control over build configuration +- Automatic generation complicates the module interface +- Reduces maintenance burden of keeping Gradle syntax current + +#### Scenario: User attempts to use generateBuildFile option +```nix +languages.kotlin = { + enable = true; + generateBuildFile = true; # This option no longer exists +}; +``` +**Expected**: Configuration validation error indicating `generateBuildFile` is not a valid option + +#### Scenario: Code generation without build files +```nix +languages.kotlin = { + enable = true; + outputPath = "gen/kotlin"; + javaOutputPath = "gen/kotlin/java"; + kotlinOutputPath = "gen/kotlin/kotlin"; + # generateBuildFile option not specified +}; +``` +**Expected**: +- Proto files are successfully compiled to Java and Kotlin +- Output directories are created as configured +- No `build.gradle.kts` or `settings.gradle.kts` files are generated +- Generation completes without warnings + +#### Scenario: Users managing their own build files +``` +project/ +├── build.gradle.kts (user-created) +├── settings.gradle.kts (user-created) +├── flake.nix +└── proto/ + └── example.proto +``` +**Expected**: +- Bufrnix generates only proto code (Java/Kotlin files) +- User's existing build files remain untouched +- No conflicts or file overwrites + +### RETAINED Requirements + +The following Kotlin features are **NOT** affected and continue to work: + +#### Requirement: Proto Code Generation +Proto files shall still be compiled to Java and Kotlin output. + +**Rationale**: This is Bufrnix's core responsibility + +#### Scenario: Basic Kotlin generation +```nix +languages.kotlin = { + enable = true; + outputPath = "gen/kotlin"; + javaOutputPath = "gen/kotlin/java"; + kotlinOutputPath = "gen/kotlin/kotlin"; +}; +``` +**Expected**: Proto files compiled to both Java and Kotlin + +#### Requirement: gRPC Support +Kotlin gRPC code generation shall continue to work when enabled. + +**Scenario**: gRPC Kotlin generation +```nix +languages.kotlin = { + enable = true; + grpc.enable = true; +}; +``` +**Expected**: gRPC Kotlin code is generated alongside proto messages + +#### Requirement: Connect RPC Support +Kotlin Connect RPC code generation shall continue to work when enabled. + +**Scenario**: Connect RPC Kotlin generation +```nix +languages.kotlin = { + enable = true; + connect.enable = true; +}; +``` +**Expected**: Connect RPC Kotlin code is generated alongside proto messages + +## Breaking Changes + +### Configuration Option Removal + +The `languages.kotlin.generateBuildFile` configuration option is **completely removed**. + +**Impact Level**: Low +- Default was `true`, but most users don't explicitly set this option +- Users relying on this feature can manually create `build.gradle.kts` files +- No proto code generation is affected + +**Migration Path for Affected Users**: +1. Remove `generateBuildFile` from flake.nix configuration +2. Create `build.gradle.kts` manually with desired Gradle configuration +3. Re-run `nix run` to generate proto code (now only) + +## Implementation Details + +### Files to Modify + +1. **`src/lib/bufrnix-options.nix`** + - Remove: `kotlin.generateBuildFile` option definition (lines 2139-2143) + +2. **`src/languages/kotlin/default.nix`** + - Simplify: `initHooks` section + - Remove: All `optionalString cfg.generateBuildFile` blocks (lines 80-154) + - Keep: Directory creation logic (`mkdir -p` commands) + +3. **`examples/kotlin-basic/flake.nix`** + - Remove: `generateBuildFile = true;` configuration line + +4. **`examples/kotlin-grpc/flake.nix`** + - Remove: `generateBuildFile = true;` configuration line + +5. **`doc/src/content/docs/reference/languages/kotlin.x-basic-configuration.nix`** + - Remove: `generateBuildFile = true;` from example configuration + +6. **`examples/kotlin-basic/README.md`** (if exists) + - Update: Remove any mention of automatic build file generation + +### Module Structure After Change + +**Before**: initHooks includes ~75 lines of build file template generation + +**After**: initHooks only includes: +```bash +mkdir -p "${javaOutputPath}" +mkdir -p "${kotlinOutputPath}" +``` + +This simplifies the module from 195 lines to approximately 120 lines. + +## Validation Criteria + +### Schema Validation +- [ ] `src/lib/bufrnix-options.nix` contains no reference to `kotlin.generateBuildFile` +- [ ] Schema compiles without errors +- [ ] Configuration validation rejects `generateBuildFile` option + +### Module Validation +- [ ] `src/languages/kotlin/default.nix` contains no reference to `generateBuildFile` +- [ ] Module syntax is valid Nix +- [ ] Output structure remains compatible with existing code + +### Example Validation +- [ ] `examples/kotlin-basic` builds successfully with `nix run` +- [ ] `examples/kotlin-grpc` builds successfully with `nix run` +- [ ] Both examples generate proto code correctly +- [ ] Neither example generates build files + +### Integration Validation +- [ ] `nix flake check` passes +- [ ] `./test-examples.sh` passes for Kotlin examples +- [ ] `./check-examples.sh` passes +- [ ] All references to `generateBuildFile` are removed + +## Related Specifications + +### Not Affected +- **Scala Language Module**: Scala's `generateBuildFile` is **retained** (separate decision) +- **Other Languages**: No other language modules use this pattern + +### Future Considerations +- Build file generation could be implemented as optional post-generation hooks +- Users needing auto-generation can create wrapper Nix functions + +## Design Rationale + +### Why Remove Instead of Deprecate? + +1. **Minimal Impact**: Very few users rely on this feature +2. **Clear Benefits**: Simplifies module interface significantly +3. **Design Alignment**: Bufrnix's core mission is protobuf code generation +4. **Low Migration Cost**: Users can easily create build files manually + +### Why Not Use Post-Generation Hooks? + +While post-generation hooks could theoretically generate build files, this approach: +- Overcomplicates the hook system with template logic +- Doesn't improve the user experience significantly +- Still requires managing Gradle syntax in Nix code + +### Why Not Follow Scala's Pattern? + +Scala's use case is different: +- Scala traditionally relies on build configuration via `build.sbt` +- The Scala ecosystem has stronger patterns for build automation +- ScalaPB generates configuration directly into `build.sbt` +- Kotlin/Gradle workflows are typically more manual + +Kotlin is better served by allowing users explicit control. + +## Questions and Answers + +**Q: What about users who depend on automatic build file generation?** +A: They can manually create `build.gradle.kts` files following Gradle's standard patterns. The generated proto code will work with any valid build configuration. + +**Q: Why not deprecate first?** +A: The feature is rarely used (minimal examples don't rely on it), and Bufrnix is pre-1.0, so breaking changes are acceptable for design improvements. + +**Q: Could this be added back as an optional plugin?** +A: Potentially, but it's outside Bufrnix's core scope. Users needing this can create their own wrapper tooling. + +**Q: Does this affect proto code generation quality?** +A: No. Only the build file generation is removed. Proto compilation is unaffected. + +## Success Criteria (For Merging) + +All of the following must be true: + +1. ✅ No reference to `generateBuildFile` remains in Kotlin code +2. ✅ All Kotlin examples pass `./test-examples.sh` +3. ✅ Schema validation passes +4. ✅ `nix flake check` passes +5. ✅ Documentation is updated +6. ✅ Generated proto code is identical (before/after) +7. ✅ No unintended changes to other language modules diff --git a/spectr/changes/remove-kotlin-generateBuildFile/tasks.md b/spectr/changes/remove-kotlin-generateBuildFile/tasks.md new file mode 100644 index 0000000..b66baa0 --- /dev/null +++ b/spectr/changes/remove-kotlin-generateBuildFile/tasks.md @@ -0,0 +1,189 @@ +# Task Breakdown: Remove cfg.generateBuildFile from Kotlin + +## Overview +Remove the `generateBuildFile` configuration option and all build file generation logic from the Kotlin language module and all references. + +## Ordered Task List + +### Phase 1: Schema Removal (Foundation) + +**Task 1.1**: Remove `generateBuildFile` option from configuration schema +- **File**: `src/lib/bufrnix-options.nix` +- **Change**: Remove lines 2139-2143 (the `generateBuildFile` mkOption definition) +- **Validation**: Schema still compiles; no syntax errors in modified file +- **Depends on**: None + +### Phase 2: Module Simplification (Core Implementation) + +**Task 2.1**: Remove build file generation from Kotlin module +- **File**: `src/languages/kotlin/default.nix` +- **Change**: + - Remove all `optionalString cfg.generateBuildFile` blocks from `initHooks` + - Keep directory creation (`mkdir -p "${javaOutputPath}"` and `mkdir -p "${kotlinOutputPath}"`) + - Remove lines 80-154 (entire build file generation section) +- **Validation**: + - Module syntax is valid + - `nix develop` still works in kotlin examples + - No reference to `generateBuildFile` remains in the file +- **Depends on**: Task 1.1 + +**Task 2.2**: Verify no dangling references in module +- **File**: `src/languages/kotlin/default.nix` +- **Validation**: Run `grep -n "generateBuildFile" src/languages/kotlin/default.nix` returns no results +- **Depends on**: Task 2.1 + +### Phase 3: Example Updates (User-Facing) + +**Task 3.1**: Update kotlin-basic example configuration +- **File**: `examples/kotlin-basic/flake.nix` +- **Change**: Remove line with `generateBuildFile = true;` +- **Validation**: + - `nix flake check` in the example directory succeeds + - Configuration is still valid +- **Depends on**: Task 1.1 + +**Task 3.2**: Update kotlin-grpc example configuration +- **File**: `examples/kotlin-grpc/flake.nix` +- **Change**: Remove line with `generateBuildFile = true;` +- **Validation**: + - `nix flake check` in the example directory succeeds + - Configuration is still valid +- **Depends on**: Task 1.1 + +**Task 3.3**: Update kotlin example README documentation +- **File**: `examples/kotlin-basic/README.md` (if present) +- **Change**: Remove any references to `generateBuildFile` configuration +- **Validation**: README is still valid Markdown; no broken references +- **Depends on**: Task 3.1 + +### Phase 4: Documentation Updates (Reference) + +**Task 4.1**: Update Kotlin configuration reference documentation +- **File**: `doc/src/content/docs/reference/languages/kotlin.x-basic-configuration.nix` +- **Change**: Remove `generateBuildFile = true;` from the example configuration +- **Validation**: + - File is valid Nix syntax + - Example configuration is complete and functional + - No reference to removed option remains +- **Depends on**: Task 1.1 + +**Task 4.2**: Update Kotlin language reference guide (if exists) +- **File**: `doc/src/content/docs/reference/languages/kotlin.md` (if present) +- **Change**: Remove any mentions of `generateBuildFile` feature +- **Validation**: Documentation builds without errors; no broken links to removed feature +- **Depends on**: Task 4.1 + +### Phase 5: Testing & Validation (Verification) + +**Task 5.1**: Run Kotlin basic example test +- **Command**: `cd examples/kotlin-basic && nix develop && nix run` +- **Validation**: + - Example builds without errors + - Proto files are generated correctly + - No build.gradle.kts is generated (expected behavior) + - Java and Kotlin output directories exist +- **Depends on**: Tasks 2.1, 3.1 + +**Task 5.2**: Run Kotlin gRPC example test +- **Command**: `cd examples/kotlin-grpc && nix develop && nix run` +- **Validation**: + - Example builds without errors + - Proto files with gRPC are generated correctly + - Java and Kotlin output directories exist +- **Depends on**: Tasks 2.1, 3.2 + +**Task 5.3**: Run comprehensive example test suite +- **Command**: `./test-examples.sh` (filter for kotlin examples) +- **Validation**: + - All Kotlin examples pass + - kotlin-basic and kotlin-grpc pass specifically + - No test failures related to missing generateBuildFile +- **Depends on**: Tasks 5.1, 5.2 + +**Task 5.4**: Run full nix flake checks +- **Command**: `nix flake check` +- **Validation**: + - All flake checks pass + - No lint errors in modified files + - Schema validation passes +- **Depends on**: All Phase 1-4 tasks + +### Phase 6: Final Verification + +**Task 6.1**: Search for any remaining references +- **Command**: `grep -r "generateBuildFile" --include="*.nix" --include="*.md" . 2>/dev/null` +- **Validation**: + - No matches in Kotlin-related files + - Only matches should be in Scala module (expected) +- **Depends on**: All Phase 1-4 tasks + +**Task 6.2**: Verify configuration schema documentation +- **Validation**: Documentation reflects that `kotlin.generateBuildFile` no longer exists +- **Depends on**: Task 4.2 (if applicable) + +## Task Dependencies Graph + +``` +Phase 1: Schema Removal + └─ Task 1.1: Remove schema option + +Phase 2: Module Simplification + └─ Task 2.1: Remove build generation (depends: 1.1) + └─ Task 2.2: Verify no references (depends: 2.1) + +Phase 3: Example Updates + ├─ Task 3.1: kotlin-basic config (depends: 1.1) + ├─ Task 3.2: kotlin-grpc config (depends: 1.1) + └─ Task 3.3: README update (depends: 3.1) + +Phase 4: Documentation + ├─ Task 4.1: Config reference (depends: 1.1) + └─ Task 4.2: Language guide (depends: 4.1) + +Phase 5: Testing + ├─ Task 5.1: Basic example test (depends: 2.1, 3.1) + ├─ Task 5.2: gRPC example test (depends: 2.1, 3.2) + ├─ Task 5.3: Full test suite (depends: 5.1, 5.2) + └─ Task 5.4: Flake checks (depends: all Phase 1-4) + +Phase 6: Final Verification + ├─ Task 6.1: Search remaining refs (depends: all Phase 1-4) + └─ Task 6.2: Documentation check (depends: 4.2) +``` + +## Parallelizable Work + +These tasks can be executed in parallel: +- Phase 2.1 and all Phase 3 tasks (after 1.1 completes) +- Phase 3 tasks (3.1, 3.2 can run together after 1.1) +- Phase 4 tasks (4.1 can run independently after 1.1) + +## Estimated Effort + +| Phase | Complexity | Time | +|-------|-----------|------| +| Phase 1 | Low | 5 min | +| Phase 2 | Low-Medium | 10 min | +| Phase 3 | Low | 5 min | +| Phase 4 | Low | 10 min | +| Phase 5 | Medium | 15 min | +| Phase 6 | Low | 5 min | +| **Total** | **Low-Medium** | **~50 min** | + +## Success Criteria + +✅ All 6 tasks must be completed +✅ All validations must pass +✅ No remaining references to `cfg.generateBuildFile` in Kotlin-related code +✅ All example tests pass +✅ Nix flake checks pass +✅ Documentation updated and consistent + +## Risk Mitigation + +| Risk | Mitigation | +|------|-----------| +| Missing a reference location | Task 6.1 verification search catches missed updates | +| Example tests fail | Phase 5 testing validates functionality before final merge | +| Schema validation failure | Task 1.1 validation ensures schema correctness immediately | +| Documentation inconsistency | Task 6.2 final verification ensures docs match code | diff --git a/spectr/changes/remove-ts-proto-generatetsconfig/design.md b/spectr/changes/remove-ts-proto-generatetsconfig/design.md new file mode 100644 index 0000000..6f82eec --- /dev/null +++ b/spectr/changes/remove-ts-proto-generatetsconfig/design.md @@ -0,0 +1,280 @@ +# Design: Remove cfg.generateTsConfig from ts-proto.nix + +## Architecture Context + +### Current State + +The ts-proto language module in `src/languages/js/ts-proto.nix` includes an optional feature that generates a `tsconfig.json` file in the output directory when `cfg.generateTsConfig` is enabled. + +**Current Flow**: +``` +User Config (flake.nix) + ↓ + └→ languages.js.tsProto.generateTsConfig = true/false + ↓ + └→ bufrnix-options.nix (defines option) + ↓ + └→ ts-proto.nix (uses option in line 89) + ↓ + └→ generateHooks writes tsconfig.json to output +``` + +**Current Implementation** (ts-proto.nix lines 88-109): +```nix +# Generate tsconfig.json if needed +${optionalString (cfg.generateTsConfig or false) '' + cat > ${outputPath}/tsconfig.json < tsconfig.json < +``` +- Clean rollback due to isolated changes +- No dependency chains to untangle + +## Design Trade-offs + +### Decision: Complete Removal vs. Deprecation + +**Chosen**: Complete removal + +**Rationale**: +- Small feature with minimal adoption (default false) +- Minimal breakage expected +- Cleaner than deprecation warning that would persist in docs +- Modern alternatives exist (protobuf-es) + +### Decision: No Replacement Auto-generation + +**Chosen**: Users manually create `tsconfig.json` + +**Rationale**: +- Config belongs in source, not generated code +- Users have framework-specific needs +- Manual creation promotes configuration awareness +- Aligns with 12-factor app principles + +## Future Considerations + +### Related Cleanups +1. **`generatePackageJson`**: Consider similar cleanup (already partially done in separate change) +2. **Configuration options review**: Periodically audit for unused options + +### Lessons Learned +1. Generated code should never generate non-code files +2. Keep configuration schema focused on core functionality +3. Prefer language-native configuration over custom generation + +## Compatibility Matrix + +### TypeScript Ecosystem Impact +- **ts-proto**: No longer generates base config (users must create own) +- **protobuf-es**: Unaffected, recommended modern alternative +- **Connect-ES**: Works with user-provided or framework tsconfig.json +- **TypeScript compiler**: Requires tsconfig.json but doesn't care where it comes from + +### Bufrnix Ecosystem Impact +- **Other language modules**: No changes needed +- **Examples**: js-es-modules needs documentation update +- **Core library**: No changes to mkBufrnix.nix + +## Success Criteria + +✅ Removal complete when: +1. Option removed from schema (bufrnix-options.nix) +2. Implementation removed (ts-proto.nix) +3. Documentation updated (README) +4. All tests pass (`./test-examples.sh`) +5. OpenSpec validation passes +6. No unintended changes to other files +7. Nix formatting correct (`nix fmt`) + +## Implementation Checklist + +- [ ] Review design with team (if applicable) +- [ ] Create tasks.md with specific change lines +- [ ] Execute Task 1: Remove option definition +- [ ] Execute Task 2: Remove implementation +- [ ] Execute Task 3: Update documentation +- [ ] Execute Task 4: Run test suite +- [ ] Execute Task 5: OpenSpec validation +- [ ] Commit changes with clear message +- [ ] Close related issues/discussions +- [ ] Update changelog/release notes diff --git a/spectr/changes/remove-ts-proto-generatetsconfig/proposal.md b/spectr/changes/remove-ts-proto-generatetsconfig/proposal.md new file mode 100644 index 0000000..c98f9a8 --- /dev/null +++ b/spectr/changes/remove-ts-proto-generatetsconfig/proposal.md @@ -0,0 +1,107 @@ +# Proposal: Remove cfg.generateTsConfig from ts-proto.nix + +**Change ID**: `remove-ts-proto-generatetsconfig` + +**Status**: Draft + +**Author**: Claude Code + +**Date**: 2025-11-13 + +## Why + +The `generateTsConfig` option violates architectural principles by: + +1. **Scope mismatch**: Configuration belongs with source code, not generated code +2. **Poor defaults**: Generic template doesn't adapt to project-specific needs +3. **Maintenance burden**: Unnecessary configuration option with low utility +4. **Better alternatives**: Modern options (protobuf-es) eliminate the need + +## Executive Summary + +Remove the `generateTsConfig` configuration option from the ts-proto language module. This option generates a basic `tsconfig.json` file in the generated code output directory, but: + +1. **Scope mismatch**: Generating configuration files belongs with the source project, not the generated code +2. **User control**: Developers should maintain their own `tsconfig.json` in their source +3. **Simplification**: Reduces configuration surface area with minimal user impact +4. **Alternative exists**: Users can easily create their own `tsconfig.json` or use ts-proto's existing TypeScript options + +## Problem Statement + +The `generateTsConfig` option in ts-proto encourages putting configuration in generated code, which violates separation of concerns: + +- Generated code should be ephemeral and replaceable +- TypeScript configuration belongs in the source project root +- The generated `tsconfig.json` is a generic template that doesn't account for project-specific needs +- Users can already rely on protobuf-es or other TypeScript generators that don't need this option + +## What Changes + +**Fully remove** the `generateTsConfig` option by: + +1. Removing the option definition from `src/lib/bufrnix-options.nix` (lines 1080-1084) +2. Removing the conditional generation block from `src/languages/js/ts-proto.nix` (lines 88-109) +3. Updating the README example in `examples/js-es-modules/README.md` to remove references +4. Verifying all tests pass without the option + +## Impact Analysis + +### Breaking Change +**Yes** - This removes a public configuration option. Users who rely on `generateTsConfig = true` will need to: +- Remove that line from their Nix configuration +- Create their own `tsconfig.json` in their project root if needed + +### Affected Areas +- **Configuration**: 1 option definition (in bufrnix-options.nix) +- **Implementation**: 1 conditional block (in ts-proto.nix) +- **Documentation**: 1 README file with example usage +- **Tests**: No dedicated tests found for this option + +### User Impact +- Low impact overall since this is an optional feature (default: `false`) +- Users actively using this option will need to add their own `tsconfig.json` +- Alternative: Use protobuf-es or other generators (already available in Bufrnix) + +## Rationale + +1. **Principle of Least Surprise**: Generated code shouldn't generate non-code configuration +2. **Maintainability**: One less configuration option to maintain and document +3. **Best Practices**: Encourages proper project structure with source-level configuration +4. **User Agency**: Developers should control their own TypeScript configuration +5. **Language Alignment**: Matches approach of other language modules (Go, Python, etc.) + +## Migration Path + +Users with `generateTsConfig = true` in their flake.nix can: + +```nix +# Before (will no longer work) +tsProto = { + enable = true; + generateTsConfig = true; +}; + +# After (recommended) +# Create tsconfig.json in your project root with appropriate settings +# Or use protobuf-es instead, which is the modern recommended approach +es = { + enable = true; + target = "ts"; +}; +``` + +## Acceptance Criteria + +- [ ] Option removed from `bufrnix-options.nix` +- [ ] Conditional block removed from `ts-proto.nix` +- [ ] README example updated or removed +- [ ] All tests pass (`./test-examples.sh` and `./check-examples.sh`) +- [ ] No compilation errors in Nix +- [ ] No validation errors with `openspec validate` + +## See Also + +- Related change: `remove-es-generatepackagejson` (similar cleanup for protobuf-es) +- Related change: `remove-js-grpc-web` (archived language module) +- Configuration reference: `src/lib/bufrnix-options.nix` +- Implementation reference: `src/languages/js/ts-proto.nix` diff --git a/spectr/changes/remove-ts-proto-generatetsconfig/specs/ts-proto-cleanup/spec.md b/spectr/changes/remove-ts-proto-generatetsconfig/specs/ts-proto-cleanup/spec.md new file mode 100644 index 0000000..4eef65f --- /dev/null +++ b/spectr/changes/remove-ts-proto-generatetsconfig/specs/ts-proto-cleanup/spec.md @@ -0,0 +1,98 @@ +# Specification: ts-proto Configuration Cleanup + +## REMOVED Requirements + +### Requirement: ts-proto tsconfig.json generation option + +**Capability**: `generateTsConfig` + +**Status**: REMOVED + +**Reason**: Configuration files belong in the source project, not in generated code. This option violated separation of concerns and provided minimal value over users creating their own TypeScript configuration. + +**Removed From**: +- Configuration schema: `src/lib/bufrnix-options.nix` (lines 1080-1084) +- Implementation: `src/languages/js/ts-proto.nix` (lines 88-109) +- Documentation: `examples/js-es-modules/README.md` (lines 142-145) + +**Details**: +The `cfg.generateTsConfig` boolean option allowed automatic generation of a basic `tsconfig.json` file in the output directory when enabled. This has been completely removed because: + +1. **Architectural concern**: Generated code should be ephemeral; configuration belongs with source +2. **Limited flexibility**: The generated template couldn't adapt to project-specific needs +3. **Maintenance cost**: Unnecessary configuration surface area for limited utility +4. **Modern alternatives**: Developers now prefer protobuf-es or manual TypeScript configuration + +**Affected Configuration Paths**: +```nix +# No longer valid: +languages.js.tsProto.generateTsConfig = true/false + +# Alternative 1: Use protobuf-es (recommended) +languages.js.es = { enable = true; target = "ts"; }; + +# Alternative 2: Create tsconfig.json in project root manually +# (Users are responsible for their own TypeScript configuration) +``` + +#### Scenario: User with existing generateTsConfig configuration + +**Given**: A user has `languages.js.tsProto.generateTsConfig = true;` in their `flake.nix` + +**When**: They update Bufrnix after this change is deployed + +**Then**: +1. Nix evaluation fails with an unknown option error +2. User must remove the line from their configuration +3. User can either: + - Switch to protobuf-es for modern TypeScript generation + - Create their own `tsconfig.json` in project root + - Use TypeScript with default settings from the language tool + +**Accepted by**: Any user willing to remove one configuration line and potentially create their own tsconfig.json + +#### Scenario: User relying on generated tsconfig.json + +**Given**: A user relied on auto-generated `tsconfig.json` in `gen/js/` output directory + +**When**: They regenerate code after this change + +**Then**: +1. The `gen/js/tsconfig.json` file is no longer created +2. User must manually create `tsconfig.json` if needed in project root +3. TypeScript tools work with configuration from source project, not generated directory + +**Accepted by**: Users willing to follow best practices of keeping config with source code + +## Impact on Other Requirements + +### No Impact On +- ✓ `languages.js.tsProto.enable` - Still required to enable ts-proto +- ✓ `languages.js.tsProto.options` - Configuration options still available +- ✓ `languages.js.tsProto.outputPath` - Output path configuration unchanged +- ✓ `languages.js.tsProto.generatePackageJson` - Separate independent option +- ✓ `languages.js.es` - Protobuf-ES generation unaffected +- ✓ `languages.js.connect` - Connect-ES generation unaffected +- ✓ `languages.js.grpcWeb` - gRPC-Web generation unaffected + +### Breaking Change Scope +- **Severity**: Low (feature disabled by default) +- **Affected Users**: Only those with `generateTsConfig = true` in their config +- **Adoption Rate**: Low (minimal usage found in codebase) +- **Migration Effort**: Minimal (remove one config line, optionally create tsconfig.json) + +## Validation Criteria + +✓ Configuration option no longer appears in schema +✓ Code generation doesn't reference `cfg.generateTsConfig` +✓ No conditional blocks for tsconfig.json generation +✓ Example documentation reflects new reality +✓ All tests pass without the feature +✓ Nix evaluation succeeds without errors + +## Specification Type + +- **Change Category**: Configuration simplification / Technical debt reduction +- **Breaking**: Yes (removes public API option) +- **Feature Addition**: No (removal only) +- **Architecture Change**: No (simplification) diff --git a/spectr/changes/remove-ts-proto-generatetsconfig/tasks.md b/spectr/changes/remove-ts-proto-generatetsconfig/tasks.md new file mode 100644 index 0000000..367e210 --- /dev/null +++ b/spectr/changes/remove-ts-proto-generatetsconfig/tasks.md @@ -0,0 +1,190 @@ +# Tasks: Remove cfg.generateTsConfig from ts-proto.nix + +## Execution Order and Dependencies + +All tasks are **independent** and can be executed in parallel after the initial review. + +--- + +## Task 1: Remove option definition from bufrnix-options.nix + +**Status**: Pending + +**Priority**: High + +**Verification**: +- [ ] Lines 1080-1084 removed from `src/lib/bufrnix-options.nix` +- [ ] No syntax errors when running `nix flake show` +- [ ] Schema validation passes: `nix eval .#schemaOutputs` (if applicable) + +**Changes**: +```nix +// File: src/lib/bufrnix-options.nix +// REMOVE these lines (1080-1084): + generateTsConfig = mkOption { + type = types.bool; + default = false; + description = "Generate tsconfig.json for the generated code"; + }; +``` + +**Notes**: This removes the configuration option from the schema, preventing users from specifying it. + +--- + +## Task 2: Remove conditional generation block from ts-proto.nix + +**Status**: Pending + +**Priority**: High + +**Verification**: +- [ ] Lines 88-109 removed from `src/languages/js/ts-proto.nix` +- [ ] File syntax valid: `nix eval src/languages/js/ts-proto.nix` +- [ ] No unintended whitespace changes + +**Changes**: +```nix +// File: src/languages/js/ts-proto.nix +// REMOVE this entire block (lines 88-109): + # Generate tsconfig.json if needed + ${optionalString (cfg.generateTsConfig or false) '' + cat > ${outputPath}/tsconfig.json < ${esOutputPath}/package.json <