From 5690c94e5eb87758600f2ebd37c81052ec1658ae Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 15 Mar 2026 18:43:40 +0200 Subject: [PATCH 01/32] refact: restructed openhands flow to opencode flow --- .agents/skills/agency-specialisation/SKILL.md | 60 ---- .agents/skills/unit-planning/SKILL.md | 31 ++ .../unit-templates/README.md | 0 .../unit-templates/api.md | 0 .../unit-templates/architecture.md | 0 .../unit-templates/bsd.md | 0 .../unit-templates/dependencies.md | 0 .../unit-templates/design.md | 0 .../unit-templates/fsd.md | 0 .../unit-templates/implementation.md | 0 .../unit-templates/migration_and_rollback.md | 0 .../unit-templates/mockups.md | 0 .../unit-templates/monitoring.md | 0 .../unit-templates/problem_space.md | 0 .../unit-templates/research.md | 0 .../unit-templates/security.md | 0 .../unit-templates/testing.md | 0 .../unit-templates/user_stories.md | 0 .agents/skills/unit-workflow/SKILL.md | 116 -------- .agents/skills/verify/SKILL.md | 106 ------- .dev/pre-commit.sh | 270 ++++++++++++++++++ .dev/setup.sh | 115 ++++++++ .opencode/agents/implementation.md | 52 ++++ .opencode/agents/orchestrator.md | 52 ++++ .opencode/agents/planning.md | 50 ++++ .opencode/agents/research.md | 52 ++++ .opencode/agents/review.md | 52 ++++ .opencode/agents/tester.md | 53 ++++ AGENTS.md | 30 +- Makefile | 70 ++++- documentation/dev.md | 37 +++ documentation/getting-started.md | 25 +- 32 files changed, 862 insertions(+), 309 deletions(-) delete mode 100644 .agents/skills/agency-specialisation/SKILL.md create mode 100644 .agents/skills/unit-planning/SKILL.md rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/README.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/api.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/architecture.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/bsd.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/dependencies.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/design.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/fsd.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/implementation.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/migration_and_rollback.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/mockups.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/monitoring.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/problem_space.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/research.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/security.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/testing.md (100%) rename .agents/skills/{unit-workflow => unit-planning}/unit-templates/user_stories.md (100%) delete mode 100644 .agents/skills/unit-workflow/SKILL.md delete mode 100644 .agents/skills/verify/SKILL.md create mode 100755 .dev/pre-commit.sh create mode 100755 .dev/setup.sh create mode 100644 .opencode/agents/implementation.md create mode 100644 .opencode/agents/orchestrator.md create mode 100644 .opencode/agents/planning.md create mode 100644 .opencode/agents/research.md create mode 100644 .opencode/agents/review.md create mode 100644 .opencode/agents/tester.md create mode 100644 documentation/dev.md diff --git a/.agents/skills/agency-specialisation/SKILL.md b/.agents/skills/agency-specialisation/SKILL.md deleted file mode 100644 index 33f611cf..00000000 --- a/.agents/skills/agency-specialisation/SKILL.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -triggers: - - merged - - next - - commit - - push - - address - - comment - - start - - begin - - work - - unit - - design - - plan - - agent - - flow - - issue - - pr - - pull - - implement ---- - -# ACE Framework Agent Specialisation - -This skill provides guidance for dynamically loading agent context based on the workflow. - -## Dependencies - -If you need agency-agents, run `cd /workspace/project/ace_prototype && ./.openhands/setup.sh` first - -## Agency Specialist Activation - -- **CRITICAL**: You MUST read the specialist agent file before activating. Do NOT guess or infer which specialist to use. - -- **Step 1**: Read the specialist file from `agency-agents/` directory - - Example: Read `agency-agents/product/product-trend-researcher.md` to activate the Trend Researcher - -- **Step 2**: Include the full path in your response to activate - - Example: "Activate the **Trend Researcher** (from `agency-agents/product/product-trend-researcher.md`)" - -- The `agency-agents/` directory contains specialized AI agents that map to different stages of the ACE Framework unit workflow. - -## Agency Mappings - -| Workflow Stage | Agency Specialist | Activation Instruction | -|---------------|-------------------|------------------------| -| **Problem Space Discovery** | Product Sprint Prioritizer | "Activate the **Sprint Prioritizer** (from `agency-agents/product/product-sprint-prioritizer.md`)" | -| **BSD (Business Spec)** | Product Sprint Prioritizer | "Activate the **Sprint Prioritizer** (from `agency-agents/product/product-sprint-prioritizer.md`)" | -| **User Stories** | Product Feedback Synthesizer | "Activate the **Feedback Synthesizer** (from `agency-agents/product/product-feedback-synthesizer.md`)" | -| **Research** | Product Trend Researcher + Testing Tool Evaluator | "Activate the **Trend Researcher** (from `agency-agents/product/product-trend-researcher.md`) for market analysis AND **Tool Evaluator** (from `agency-agents/testing/testing-tool-evaluator.md`)" | -| **Backend Implementation** | Backend Architect | "Activate the **Backend Architect** (from `agency-agents/engineering/engineering-backend-architect.md`). Also read `design/README.md` for ACE-specific patterns." | -| **Frontend Implementation** | Frontend Developer | "Activate the **Frontend Developer** (from `agency-agents/engineering/engineering-frontend-developer.md`)" | -| **DevOps/Infrastructure** | DevOps Automator | "Activate the **DevOps Automator** (from `agency-agents/engineering/engineering-devops-automator.md`)" | -| **Security Review** | Security Engineer | "Activate the **Security Engineer** (from `agency-agents/engineering/engineering-security-engineer.md`)" | -| **Testing - Evidence** | Testing Evidence Collector | "Activate the **Evidence Collector** (from `agency-agents/testing/testing-evidence-collector.md`)" | -| **Testing - Quality Gate** | Testing Reality Checker | "Activate the **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`)" | -| **Testing - API** | Testing API Tester | "Activate the **API Tester** (from `agency-agents/testing/testing-api-tester.md`)" | -| **Testing - Performance** | Testing Performance Benchmarker | "Activate the **Performance Benchmarker** (from `agency-agents/testing/testing-performance-benchmarker.md`)" | -| **Code Review** | Senior Developer + Reality Checker | "Activate the **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) AND **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`)" | -| **UX Design** | UI Designer + UX Researcher | "Activate the **UI Designer** (from `agency-agents/design/design-ui-designer.md`) AND **UX Researcher** (from `agency-agents/design/design-ux-researcher.md`)" | diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md new file mode 100644 index 00000000..0bce49a3 --- /dev/null +++ b/.agents/skills/unit-planning/SKILL.md @@ -0,0 +1,31 @@ +--- +name: unit-planning +description: Provides templates for planning agents to create unit design documents +--- + +# Unit Planning Templates + +This skill provides templates for creating unit design documents. + +## Templates + +Located in `.agents/skills/unit-planning/unit-templates/`: +- `problem_space.md` - Problem exploration +- `bsd.md` - Business Specification +- `user_stories.md` - User stories +- `research.md` - Technology research +- `fsd.md` - Functional Specification +- `architecture.md` - Technical architecture +- `implementation.md` - Implementation plan +- `security.md` - Security considerations +- `testing.md` - Testing strategy +- `api.md` - API specifications +- `migration_and_rollback.md` - Database migrations +- `monitoring.md` - Observability + +## Usage + +When creating a design document: +1. Read the relevant template from `.agents/skills/unit-planning/unit-templates/{template_name}.md` +2. Fill in the template based on the unit context +3. Save to `design/units/{UNIT_NAME}/{template_name}.md` diff --git a/.agents/skills/unit-workflow/unit-templates/README.md b/.agents/skills/unit-planning/unit-templates/README.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/README.md rename to .agents/skills/unit-planning/unit-templates/README.md diff --git a/.agents/skills/unit-workflow/unit-templates/api.md b/.agents/skills/unit-planning/unit-templates/api.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/api.md rename to .agents/skills/unit-planning/unit-templates/api.md diff --git a/.agents/skills/unit-workflow/unit-templates/architecture.md b/.agents/skills/unit-planning/unit-templates/architecture.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/architecture.md rename to .agents/skills/unit-planning/unit-templates/architecture.md diff --git a/.agents/skills/unit-workflow/unit-templates/bsd.md b/.agents/skills/unit-planning/unit-templates/bsd.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/bsd.md rename to .agents/skills/unit-planning/unit-templates/bsd.md diff --git a/.agents/skills/unit-workflow/unit-templates/dependencies.md b/.agents/skills/unit-planning/unit-templates/dependencies.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/dependencies.md rename to .agents/skills/unit-planning/unit-templates/dependencies.md diff --git a/.agents/skills/unit-workflow/unit-templates/design.md b/.agents/skills/unit-planning/unit-templates/design.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/design.md rename to .agents/skills/unit-planning/unit-templates/design.md diff --git a/.agents/skills/unit-workflow/unit-templates/fsd.md b/.agents/skills/unit-planning/unit-templates/fsd.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/fsd.md rename to .agents/skills/unit-planning/unit-templates/fsd.md diff --git a/.agents/skills/unit-workflow/unit-templates/implementation.md b/.agents/skills/unit-planning/unit-templates/implementation.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/implementation.md rename to .agents/skills/unit-planning/unit-templates/implementation.md diff --git a/.agents/skills/unit-workflow/unit-templates/migration_and_rollback.md b/.agents/skills/unit-planning/unit-templates/migration_and_rollback.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/migration_and_rollback.md rename to .agents/skills/unit-planning/unit-templates/migration_and_rollback.md diff --git a/.agents/skills/unit-workflow/unit-templates/mockups.md b/.agents/skills/unit-planning/unit-templates/mockups.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/mockups.md rename to .agents/skills/unit-planning/unit-templates/mockups.md diff --git a/.agents/skills/unit-workflow/unit-templates/monitoring.md b/.agents/skills/unit-planning/unit-templates/monitoring.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/monitoring.md rename to .agents/skills/unit-planning/unit-templates/monitoring.md diff --git a/.agents/skills/unit-workflow/unit-templates/problem_space.md b/.agents/skills/unit-planning/unit-templates/problem_space.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/problem_space.md rename to .agents/skills/unit-planning/unit-templates/problem_space.md diff --git a/.agents/skills/unit-workflow/unit-templates/research.md b/.agents/skills/unit-planning/unit-templates/research.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/research.md rename to .agents/skills/unit-planning/unit-templates/research.md diff --git a/.agents/skills/unit-workflow/unit-templates/security.md b/.agents/skills/unit-planning/unit-templates/security.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/security.md rename to .agents/skills/unit-planning/unit-templates/security.md diff --git a/.agents/skills/unit-workflow/unit-templates/testing.md b/.agents/skills/unit-planning/unit-templates/testing.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/testing.md rename to .agents/skills/unit-planning/unit-templates/testing.md diff --git a/.agents/skills/unit-workflow/unit-templates/user_stories.md b/.agents/skills/unit-planning/unit-templates/user_stories.md similarity index 100% rename from .agents/skills/unit-workflow/unit-templates/user_stories.md rename to .agents/skills/unit-planning/unit-templates/user_stories.md diff --git a/.agents/skills/unit-workflow/SKILL.md b/.agents/skills/unit-workflow/SKILL.md deleted file mode 100644 index f9159a7f..00000000 --- a/.agents/skills/unit-workflow/SKILL.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -triggers: - - unit - - units - - BSD - - bsd - - user_stories - - research - - FSD - - fsd - - implementation - - architecture - - problem - - plan - - planning - - design document - - design documents ---- - -# ACE Framework Unit Workflow - -This skill provides guidance for working with units in the ACE Framework. Units are discrete pieces of work that can be independently designed, implemented, and documented. - -## What are Units? - -Units are discrete pieces of work in the ACE Framework. Each unit represents a feature, component, or refactoring that can be independently designed, implemented, and documented. - -**Examples:** -- Adding a new API endpoint -- Creating a new UI component -- Implementing a database migration -- Refactoring existing code - -## Unit Template Structure - -Each unit should have a complete set of documentation in `design/units//`: - -Refer to the `unit-templates/` folder to see them all. - -## Unit Workflow - -Follow these steps when working on a unit: - -### 1. Skeleton - -1. Create the unit folder -```bash -mkdir -p design/units/ -``` - -2. Create the readme in the unit folder based off the `unit-templates/README.md` - -3. Link the readme in the units readme - - -### 2. Problem Space Discovery (Before Each Document) - -**IMPORTANT**: Before starting any document in a unit, explore the topic with the user through questions. - -1. **Question Loop Process**: For each document (BSD, user_stories, research, FSD, architecture, implementation, etc.): -- Ask clarifying questions about what's needed for that specific document -- Don't assume - ask until you understand -- Document the Q&A in the relevant section -2. **Initial Discovery**: Ask clarifying questions to understand: -- What problem are we trying to solve? -- Who are the users? -- What are the success criteria? -- What constraints exist (budget, timeline, tech stack)? -3. **Iterative Exploration**: Ask follow-up questions in a loop until the problem space is fully understood: -- Clarify ambiguous requirements -- Explore edge cases -- Identify dependencies and integrations -- Understand non-functional requirements (performance, security, scalability) -4. **Document Findings**: The answers form the relevant document (problem_space.md, user_stories.md, etc.) -5. **Do NOT proceed to writing** until you have a clear understanding. It is better to ask more questions than to assume. - -### 3. Complete Planning Documents - -**One document type per PR** (e.g., one PR for research, one for BSD). - -Complete ALL planning documents BEFORE writing any code: -1. Start with **problem_space.md** to explore the problem through questions (REQUIRED) -2. Create **bsd.md** to define the business case -3. Create **user_stories.md** to capture user requirements -4. Conduct **research.md** to evaluate different approaches and make informed design decisions -5. Write **fsd.md** for technical details -6. Design **architecture.md** for system integration -7. Plan **implementation.md** for execution -8. Document **security.md** considerations -9. Complete remaining documents as needed - -## Unit Completion Workflow - -When all design documents for a unit have been approved and merged: -1. file_editor the unit's implementation document (implementation.md) to understand the work breakdown -2. Create detailed GitHub issues that break the implementation into micro-PRs (the smallest divisible units of work) -3. Each issue should: - - Have a clear, focused title describing one specific task - - Detail that the agent must read `design/README.md` and `design/units//` before starting - - Reference the relevant unit name and document - - Include acceptance criteria from the user stories or implementation plan - - **IMPORTANT**: Include instruction that the agent MUST respond to the issue with the PR link once created - - Be small enough to be implemented in a single PR -4. Create one GitHub issue per micro-PR -5. After creating all issues, update the changelog with a summary of the issues created -6. Link these issues in the unit's README for tracking - - -### Technology Recommendations - -When suggesting technologies, libraries, or frameworks: -1. **Always perform web searches** to find current options -2. **Provide multiple alternatives** - never recommend just one -3. **Verify active maintenance** - check GitHub activity, last release date, issue response time -4. **Recommend latest stable versions** - check for the most recent releases -5. **Consider community adoption** - look at stars, downloads, and real-world usage diff --git a/.agents/skills/verify/SKILL.md b/.agents/skills/verify/SKILL.md deleted file mode 100644 index 8731e297..00000000 --- a/.agents/skills/verify/SKILL.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -name: verify -description: This skill should be used when the user sends a message starting with "/verify" to request confirmation that the agent has completed all required startup and setup steps before beginning any work. Use this skill to verify the agent is properly configured. -triggers: - - /verify - - verify - - merged - - next - - commit - - push - - address - - comment - - start - - begin - - work - - unit - - design - - plan - - agent - - flow - - issue - - pr - - pull - - implement - - units - - BSD - - bsd - - user_stories - - research - - FSD - - fsd - - implementation - - architecture - - problem - - planning - - design document - - design documents ---- - -# Verify Skill - -This skill confirms that all required setup steps have been completed before starting any work. - -## CRITICAL: This skill MUST be activated on EVERY request - -**BEFORE responding to any user request, you MUST:** -1. Run the setup script (if not already run this session) -2. file_editor the design documentation -3. Activate the appropriate agency specialist -4. **Explicitly state the activation** using the format below - -## Activation Steps (IN ORDER) - -### Step 1: Setup Script -Run: `cd /workspace/project/ace_prototype && ./.openhands/setup.sh` -- Only run once per session -- Verify: Go, Node.js, Docker, agency-agents exist - -### Step 2: Design Documentation -file_editor: -- `design/README.md` -- `design/units/README.md` -- Relevant unit documentation - -### Step 3: Agency Specialisation -**READ the agency specialisation skill file:** -- Read: `.agents/skills/agency-specialisation/SKILL.md` (this file tells you which specialist to use) -- file_editor the relevant specialist's file from `agency-agents/` directory -- Activate by stating their name with the full path - -### Step 4: State Activation (MANDATORY) -**You MUST respond with this exact format:** - -``` -✅ Setup Verified - -- ✅ Setup script executed -- ✅ Design documentation read -- ✅ AGENTS.md instructions digested -- ✅ Agency specialisation activated - - activated -``` - -Replace `` with the actual specialist name from Step 3. - -## Examples - -**Correct:** -``` -User: /verify - -Agent: ✅ Setup Verified - -- ✅ Setup script executed -- ✅ Design documentation read -- ✅ AGENTS.md instructions digested -- ✅ Agency specialisation activated - -Trend Researcher + Tool Evaluator activated -``` - -**Incorrect (do NOT do this):** -- Just proceeding without verification -- Not stating the specialist name -- Skipping any step diff --git a/.dev/pre-commit.sh b/.dev/pre-commit.sh new file mode 100755 index 00000000..a2ae47c4 --- /dev/null +++ b/.dev/pre-commit.sh @@ -0,0 +1,270 @@ +#!/bin/bash +# +# Quality gates that run before every commit to enforce code quality. +# This script should be run before committing to ensure all quality checks pass. +# + +set +euo pipefail + +# Get the directory where this script is located +# Resolve symlinks to get the actual script location (handles git hook symlink case) +SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || echo "${BASH_SOURCE[0]}")" +SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Track if we're in a git repository +IS_GIT_REPO=false +if [ -d "$REPO_ROOT/.git" ]; then + IS_GIT_REPO=true +fi + +log_info() { + echo -e "${BLUE}[PRE-COMMIT]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[PASS]${NC} $1" +} + +log_fail() { + echo -e "${RED}[FAIL]${NC} $1" +} + +log_skip() { + echo -e "${YELLOW}[SKIP]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Change to repo root +cd "$REPO_ROOT" + +# Track overall status +FAILED=0 +SKIPPED=0 + +echo "" +echo "==========================================" +echo " Pre-Commit Quality Gates" +echo "==========================================" +echo "" + +# ============================================ +# 1. Go Build Verification +# ============================================ +log_info "1/4: Go Build Verification..." + +cd "$REPO_ROOT/backend" + +# Check if go.work exists +if [ ! -f "go.work" ]; then + log_skip "No Go workspace found, skipping build verification" + ((SKIPPED++)) +else + # Build all modules in the workspace individually + BUILD_SUCCESS=true + BUILD_WARNINGS=false + for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + if [ -d "$module" ] && [ -f "$module/go.mod" ]; then + log_info "Building $module..." + BUILD_OUTPUT=$(cd "$module" && go build ./... 2>&1) + if [ $? -ne 0 ]; then + # Check if this is a pre-existing issue (not introduced by recent changes) + log_warn "Build issue in $module (may be pre-existing):" + echo "$BUILD_OUTPUT" | head -5 + BUILD_WARNINGS=true + fi + fi + done + + if [ "$BUILD_WARNINGS" = true ]; then + log_warn "Build verification had warnings (pre-existing issues detected)" + fi + log_success "Go build verification complete" +fi + +echo "" + +# ============================================ +# 2. SQLC Generate Validation +# ============================================ +log_info "2/4: SQLC Generate Validation..." + +cd "$REPO_ROOT/backend" + +# Track if any sqlc.yaml files exist +SQLC_EXISTS=false +SQLC_FAILED=false + +# Check each module in the workspace +for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + if [ -d "$module" ] && [ -f "$module/sqlc.yaml" ]; then + SQLC_EXISTS=true + log_info "Running sqlc generate for $module..." + + # Save current generated files for comparison + if [ -d "$module/sqlc" ]; then + TEMP_DIR=$(mktemp -d) + cp -r "$module/sqlc" "$TEMP_DIR/sqlc_backup" + + # Generate new files + if (cd "$module" && sqlc generate 2>&1); then + # Compare to see if anything changed + if diff -rq "$TEMP_DIR/sqlc_backup" "$module/sqlc" > /dev/null 2>&1; then + log_success "sqlc generate for $module - no changes needed" + else + log_warn "sqlc generate for $module - generated files are out of date" + log_info "Run 'sqlc generate' in $module to update generated files" + fi + + # Clean up + rm -rf "$TEMP_DIR" + else + log_warn "sqlc generate for $module had issues (may be pre-existing)" + fi + else + # No existing generated files, just run generate + if (cd "$module" && sqlc generate 2>&1); then + log_success "sqlc generate for $module - generated successfully" + else + log_warn "sqlc generate for $module had issues (may be pre-existing)" + fi + fi + fi +done + +if [ "$SQLC_EXISTS" = false ]; then + log_skip "No sqlc.yaml files found, skipping SQLC validation" + ((SKIPPED++)) +elif ! command -v sqlc &> /dev/null; then + log_skip "sqlc not installed, skipping SQLC validation" + ((SKIPPED++)) +else + log_success "SQLC validation complete" +fi + +echo "" + +# ============================================ +# 3. Go Test Suite +# ============================================ +log_info "3/4: Go Test Suite..." + +cd "$REPO_ROOT/backend" + +# Check if go.work exists +if [ ! -f "go.work" ]; then + log_skip "No Go workspace found, skipping test suite" + ((SKIPPED++)) +else + # Test all modules in the workspace individually + TEST_SUCCESS=true + for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + if [ -d "$module" ] && [ -f "$module/go.mod" ]; then + if find "$module" -name "*_test.go" -type f 2>/dev/null | grep -q .; then + log_info "Testing $module..." + if ! (cd "$module" && go test -v ./...) 2>&1; then + log_warn "Tests failed or had issues in $module" + fi + fi + fi + done + + log_success "Go test suite complete" +fi + +echo "" + +# ============================================ +# 4. Frontend Lint (svelte-check) +# ============================================ +log_info "4/4: Frontend Lint..." + +cd "$REPO_ROOT/frontend" + +if [ -f "package.json" ]; then + # Check if svelte-kit is set up (need .svelte-kit directory) + if [ -d ".svelte-kit" ]; then + # Run svelte-check for TypeScript and Svelte validation + if npx svelte-check --threshold warning 2>&1; then + log_success "Frontend lint passed" + else + log_warn "Frontend lint had warnings" + fi + elif [ -d "node_modules" ]; then + log_info "SvelteKit not initialized, running svelte-kit sync..." + if npx svelte-kit sync 2>&1; then + log_success "SvelteKit sync complete" + if npx svelte-check --threshold warning 2>&1; then + log_success "Frontend lint passed" + else + log_warn "Frontend lint had warnings" + fi + else + log_skip "SvelteKit setup incomplete, skipping frontend lint" + ((SKIPPED++)) + fi + else + log_skip "No node_modules found, skipping frontend lint" + ((SKIPPED++)) + fi +else + log_skip "No frontend package.json found, skipping lint" + ((SKIPPED++)) +fi + +echo "" + +# ============================================ +# Summary +# ============================================ +echo "==========================================" +echo " Pre-Commit Quality Gates Summary" +echo "==========================================" +echo "" + +# Count warnings +WARNINGS=0 +if [ -n "${BUILD_WARNINGS:-}" ] && [ "$BUILD_WARNINGS" = true ]; then + ((WARNINGS++)) +fi + +if [ $FAILED -gt 0 ]; then + echo -e "${RED}$FAILED quality gate(s) FAILED${NC}" + echo "" + echo "Please fix the failing checks before committing." + echo "" + exit 1 +elif [ $WARNINGS -gt 0 ]; then + echo -e "${YELLOW}Quality gates completed with warnings${NC}" + echo "" + echo "Warnings indicate pre-existing issues or configuration problems." + echo "Review the output above for details." + echo "" + exit 0 +elif [ $SKIPPED -gt 0 ]; then + echo -e "${GREEN}All quality gates passed (or skipped)${NC}" + echo "" + echo "Passed: $((4 - SKIPPED - FAILED))" + echo "Skipped: $SKIPPED" + echo "Failed: $FAILED" + echo "" + exit 0 +else + echo -e "${GREEN}All quality gates PASSED!${NC}" + echo "" + exit 0 +fi diff --git a/.dev/setup.sh b/.dev/setup.sh new file mode 100755 index 00000000..63529361 --- /dev/null +++ b/.dev/setup.sh @@ -0,0 +1,115 @@ +#!/bin/bash +# +# .dev/setup.sh +# +# Installs all development dependencies inside the distrobox. +# Run this after first creating the distrobox. +# + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { + echo -e "${BLUE}[SETUP]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[OK]${NC} $1" +} + +# Check if we're in distrobox +if [ ! -f /run/.toolboxenv ]; then + echo "This script must be run inside the distrobox" + echo "Run: distrobox enter opencode" + exit 1 +fi + +# Ensure opencode PATH is available +export PATH="$HOME/.opencode/bin:$PATH" + +# Check if already set up (idempotency) +log_info "Checking existing installation..." +SKIP_SETUP=true + +for cmd in git make go node npm docker opencode; do + if ! command -v $cmd >/dev/null 2>&1; then + SKIP_SETUP=false + break + fi +done || true + +if [ "$SKIP_SETUP" = true ]; then + log_success "All dependencies already installed!" + exit 0 +fi + +log_info "Installing development dependencies..." + +# Helper to run dnf with or without sudo +run_dnf() { + sudo dnf "$@" || dnf "$@" +} + +# Update package manager +log_info "Updating package manager..." +run_dnf update -y + +# Install core tools +log_info "Installing core tools..." +run_dnf install -y \ + git \ + make \ + curl \ + wget \ + golang \ + nodejs \ + npm \ + python3 \ + python3-pip \ + docker \ + which \ + findutils \ + jq + +# Install pipx (needed for distrobox) +log_info "Installing pipx..." +pip3 install --user pipx +pipx ensurepath + +# Run go mod tidy for backend dependencies +log_info "Running go mod tidy..." +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +if [ -d "$REPO_DIR/backend" ]; then + cd "$REPO_DIR/backend" + for module in $(go work edit -json 2>/dev/null | jq -r '.Use[] | .DiskPath' 2>/dev/null || echo ""); do + if [ -d "$module" ] && [ -f "$module/go.mod" ]; then + log_info "Tidying $module..." + (cd "$module" && go mod tidy 2>/dev/null || true) + fi + done +fi + +# Install OpenCode +log_info "Installing OpenCode..." +if ! command -v opencode &> /dev/null; then + curl -fsSL https://opencode.ai/install | bash +fi +export PATH="$HOME/.opencode/bin:$PATH" +echo "export PATH=\"\$HOME/.opencode/bin:\$PATH\"" >> ~/.bashrc 2>/dev/null || true + +# Verify installations +log_info "Verifying tools..." +command -v git >/dev/null 2>&1 && log_success "git" +command -v make >/dev/null 2>&1 && log_success "make" +command -v go >/dev/null 2>&1 && log_success "go" +command -v node >/dev/null 2>&1 && log_success "node" +command -v npm >/dev/null 2>&1 && log_success "npm" +command -v docker >/dev/null 2>&1 && log_success "docker" +command -v opencode >/dev/null 2>&1 && log_success "opencode" + +log_success "Development environment ready!" diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md new file mode 100644 index 00000000..1c195157 --- /dev/null +++ b/.opencode/agents/implementation.md @@ -0,0 +1,52 @@ +--- +description: Unit implementation - architecture and implementation planning +mode: subagent +--- + +# Unit Implementation Agent + +Activate the **Backend Architect** (from `agency-agents/engineering/engineering-backend-architect.md`) +Also read `design/README.md` for ACE-specific patterns. + +## Your Task + +Complete the implementation planning phase for the unit specified by the user. + +## Context + +- Read ALL planning documents in `design/units/{UNIT_NAME}/` first +- Read `design/README.md` for ACE Framework patterns + +## Workflow + +### 1. Architecture Design +Create `architecture.md`: +- System components +- Data flow +- Integration points + +### 2. Implementation Plan +Create `implementation.md`: +- Breakdown into micro-PRs +- Each PR should be independently testable +- Include acceptance criteria + +### 3. Security +Create `security.md` + +### 4. Additional Documents as needed +- `api.md` - API specifications +- `migration_and_rollback.md` - Database migrations +- `monitoring.md` - Observability requirements + +## Templates + +Use templates from `.agents/skills/unit-workflow/unit-templates/`: +- `architecture.md` +- `implementation.md` +- `security.md` + +## Output + +Create all documents in `design/units/{UNIT_NAME}/` +Return the implementation breakdown with micro-PRs suggested. diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md new file mode 100644 index 00000000..5193192d --- /dev/null +++ b/.opencode/agents/orchestrator.md @@ -0,0 +1,52 @@ +--- +description: Orchestrates the full unit workflow across planning, research, implementation, and review +mode: subagent +--- + +# Unit Workflow Orchestrator + +You orchestrate the complete ACE Framework unit workflow by delegating to specialized subagents. + +## Available Subagents + +| Subagent | Purpose | +|----------|---------| +| `planning` | Problem space, BSD, user stories | +| `research` | Research, FSD | +| `implementation` | Architecture, implementation plan | +| `review` | Code review | +| `tester` | Runs tests via docker/make | + +## Workflow + +### Step 1: Understand Current State +1. Read `design/units/` to see existing units +2. If unit exists, read its documents to see what's completed +3. Determine which phase to work on next + +### Step 2: Delegate to Subagent +Use Task tool to invoke the appropriate subagent: +- `@planning` for planning phase +- `@research` for research phase +- `@implementation` for implementation phase +- `@review` for review phase +- `@tester` for running tests + +### Step 3: Report Results +Return a summary of what was accomplished and what's next. + +## Usage + +User: "Start the observability unit" +1. Check `design/units/observability/` status +2. Launch `@planning` subagent +3. Report results + +User: "Continue the core-api unit" +1. Check `design/units/core-api/` status +2. Launch appropriate subagent for next phase +3. Report results + +User: "Run tests for the changes" +1. Launch `@tester` subagent +2. Report results diff --git a/.opencode/agents/planning.md b/.opencode/agents/planning.md new file mode 100644 index 00000000..e301885a --- /dev/null +++ b/.opencode/agents/planning.md @@ -0,0 +1,50 @@ +--- +description: Unit planning - problem space, BSD, and user stories +mode: subagent +--- + +# Unit Planning Agent + +Activate the **Sprint Prioritizer** (from `agency-agents/product/product-sprint-prioritizer.md`) + +## Your Task + +Complete the planning phase for the unit specified by the user. + +## Context + +- Read `design/README.md` for ACE Framework patterns +- Read `design/units/README.md` to see existing units +- Unit directory: `design/units/{UNIT_NAME}/` + +## Workflow + +### 1. Problem Space Discovery +Before any document writing, explore the problem through questions: +- What problem are we solving? +- Who are the users? +- What are success criteria? +- What constraints exist? + +Ask clarifying questions until problem space is fully understood. Document in `problem_space.md`. + +### 2. Business Specification (BSD) +Define the business case in `bsd.md`: +- Business value +- Success metrics +- Scope definition +- Dependencies + +### 3. User Stories +Capture user requirements in `user_stories.md` with acceptance criteria. + +## Templates + +Use templates from `.agents/skills/unit-workflow/unit-templates/`: +- `bsd.md` +- `user_stories.md` + +## Output + +Create all documents in `design/units/{UNIT_NAME}/` +Return the file paths created and any questions that need user input. diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md new file mode 100644 index 00000000..bb29f230 --- /dev/null +++ b/.opencode/agents/research.md @@ -0,0 +1,52 @@ +--- +description: Unit research - technology evaluation and FSD +mode: subagent +--- + +# Unit Research Agent + +Activate the **Trend Researcher** (from `agency-agents/product/product-trend-researcher.md`) +Activate **Tool Evaluator** (from `agency-agents/testing/testing-tool-evaluator.md`) + +## Your Task + +Complete the research phase for the unit specified by the user. + +## Context + +- Read `design/units/{UNIT_NAME}/` existing documents first +- Read `design/README.md` for ACE Framework patterns + +## Workflow + +### 1. Technology Research +Research and evaluate different approaches: +- Compare technology options +- Check active maintenance (GitHub activity, last release) +- Provide multiple alternatives, never just one +- Verify with web searches for current best practices + +### 2. Research Document +Create `research.md`: +- Problem space summary +- Technology options evaluated +- Recommendations with rationale +- Trade-offs considered + +### 3. Functional Specification (FSD) +Create `fsd.md`: +- Functional requirements +- API contracts +- Data models +- Edge cases + +## Templates + +Use templates from `.agents/skills/unit-workflow/unit-templates/`: +- `research.md` +- `fsd.md` + +## Output + +Create documents in `design/units/{UNIT_NAME}/` +Return file paths created and technology recommendations. diff --git a/.opencode/agents/review.md b/.opencode/agents/review.md new file mode 100644 index 00000000..571be6c1 --- /dev/null +++ b/.opencode/agents/review.md @@ -0,0 +1,52 @@ +--- +description: Unit review and testing +mode: subagent +--- + +# Unit Review Agent + +For Code Review: Activate the **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) +For Testing: Activate the **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) + +## Your Task + +Complete the review and testing phase for the unit specified by the user. + +## Context + +- Read all implementation documents in `design/units/{UNIT_NAME}/` +- Implementation is in `backend/` and/or `frontend/` + +## Workflow + +### 1. Testing Strategy +Create `testing.md`: +- Unit test requirements (80% coverage target) +- Integration test requirements +- E2E test requirements + +### 2. Code Review +- Review implementation against `fsd.md` and `architecture.md` +- Check for: + - Security vulnerabilities + - Error handling completeness + - Test coverage + - Code quality + +### 3. Evidence Collection +Activate **Evidence Collector** (from `agency-agents/testing/testing-evidence-collector.md`) to gather test evidence + +### 4. Quality Gate +Activate **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) to verify quality gates + +## Templates + +Use templates from `.agents/skills/unit-workflow/unit-templates/`: +- `testing.md` + +## Output + +- Updated `testing.md` with test cases +- Review findings +- Quality gate status +- Any issues that need fixing diff --git a/.opencode/agents/tester.md b/.opencode/agents/tester.md new file mode 100644 index 00000000..e08ab802 --- /dev/null +++ b/.opencode/agents/tester.md @@ -0,0 +1,53 @@ +--- +description: Runs tests for code changes using docker/make +mode: subagent +--- + +# Unit Tester Agent + +This agent runs tests for code changes in a safe manner. + +## CRITICAL: Local Machine Restrictions + +This is running on the user's LOCAL machine. You MUST only use: +- `make` commands from Makefile +- `docker exec` commands to run tests inside containers +- `curl` to test HTTP endpoints + +**NEVER run arbitrary commands directly on the host.** + +## Testing Commands + +### Start Services +```bash +make up +``` + +### Run Tests +```bash +make test +``` + +### Run API Tests Directly +```bash +docker exec ace_api go test ./... +``` + +### Test HTTP Endpoints +```bash +curl -X GET http://localhost:8080/health +``` + +## Workflow + +1. Start services with `make up` if not running +2. Run tests with `make test` +3. If tests fail, investigate with `docker exec` commands +4. Test specific endpoints with `curl` +5. Report results + +## Output + +- Test results (pass/fail) +- Any errors encountered +- Suggestions for fixes if tests fail diff --git a/AGENTS.md b/AGENTS.md index 166fa34c..b2005ccc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,19 +1,29 @@ **CRITICAL** paths are non-negotiable steps, if you don't adhere to any of the **CRITICAL** steps, your work will be invalidated and thrown out. # Startup -- **CRITICAL**: On initialisation before responding to any messages from the user, run the `cd /workspace/project/ace_prototype && ./.openhands/setup.sh` script. This will install all your tooling(go, npm, docker, etc), git hooks & installs the agency_agents files for the agent specialisation tool. -- MAKE SURE TO RUN THIS SCRIPT BEFORE DOING ANY WORK, THIS MUST ALWAYS BE THE FIRST THING YOU DO!!! +- **CRITICAL**: On initialisation before responding to any messages from the user, run `make setup` to ensure agency-agents is available and distrobox is set up. This will clone the repo if not present. # Design Documentation (Always Read First!) - **CRITICAL**: Always read `design/README.md` before starting any work - Reference `design/units/README.md` for individual unit documentation - Understanding the overall system design is essential before making any changes -# Agency Specialisation -- **CRITICAL**: BEFORE EVERY ACTION(Starting a unit, Planning&Creating a document, Creating Issues, Starting a Phase, Writing/Reviewing/Testing code, Responding to the user), MAKE SURE TO USE THE Agency Specialisation SKILL AND DO YOUR Agency Specialisation Activation +# Unit Workflow +- **CRITICAL**: When working on units, ALWAYS use the Task tool to invoke `@orchestrator`. The orchestrator handles delegation to planning, research, implementation, review, and testing phases. +- Load `unit-planning` skill for template access when creating planning documents + +# OpenCode Agents + +| Agent | Purpose | +|-------|---------| +| `orchestrator` | Orchestrates the full unit workflow | +| `planning` | Problem space, BSD, user stories | +| `research` | Research, FSD | +| `implementation` | Architecture, implementation plan | +| `review` | Code review | +| `tester` | Runs tests via docker/make | # Project Structure -The ace_prototype repository is organized as follows: - `agency-agents` - Bespoke workflow instructions - `design/` - All design documentation for the system - `design/README.md` - Overall system architecture and design @@ -24,6 +34,16 @@ The ace_prototype repository is organized as follows: - `backend/` - Go backend source code (when implemented) - `frontend/` - SvelteKit/TypeScript frontend source code (when implemented) +# Testing (Local Machine) +- **CRITICAL**: When testing on this local machine, ONLY use: + - `make` commands from Makefile + - `docker exec` commands to run tests inside containers + - `curl` to test HTTP endpoints +- **NEVER** run arbitrary commands directly on the host +- Use `make up` to start services, `make test` to run tests +- Use `docker exec` to run Go tests inside the api container +- Use `curl` to test API endpoints + # Documentation Updates **IMPORTANT**: Before making any changelog or documentation updates: diff --git a/Makefile b/Makefile index 60a0738e..94b523d8 100644 --- a/Makefile +++ b/Makefile @@ -23,13 +23,18 @@ endif COMPOSE := $(ORCHESTRATOR) compose -f devops/$(ENVIRONMENT)/compose.yml -# Colors -GREEN := \033[0;32m -YELLOW := \033[0;33m -BLUE := \033[0;34m -NC := \033[0m # No Color +# Distrobox config +DISTROBOX_NAME := opencode +DISTROBOX_IMAGE := fedora:latest -.PHONY: help up down logs logs-api logs-fe logs-db logs-broker clean re build ps test +# Colors (use shell to properly interpret escape codes) +GREEN := $(shell printf '\033[0;32m') +YELLOW := $(shell printf '\033[0;33m') +BLUE := $(shell printf '\033[0;34m') +RED := $(shell printf '\033[0;31m') +NC := $(shell printf '\033[0m') + +.PHONY: help up down logs logs-api logs-fe logs-db logs-broker clean re build ps test dev agent agent-stop ##@ General @@ -48,6 +53,59 @@ help: ## Show this help message @echo " CONTAINER_ORCHESTRATOR Container runtime (docker or podman) [default: docker]" @echo "" +##@ Development Environment + +dev: ## Full dev setup: clone agency-agents, setup distrobox, install deps + @echo "$(BLUE)Setting up development environment...$(NC)" + @echo "" + @# Step 1: Clone/update agency-agents + @if [ -d "agency-agents" ]; then \ + echo "Updating agency-agents..."; \ + cd agency-agents && git pull; \ + else \ + echo "Cloning agency-agents..."; \ + git clone https://github.com/msitarzewski/agency-agents.git; \ + fi + @echo "" + @# Step 2: Check/create distrobox + @echo "$(BLUE)Checking distrobox...$(NC)" + @if ! command -v distrobox &> /dev/null; then \ + echo "$(RED)Error: distrobox not installed. Install with: pipx install distrobox$(NC)"; \ + exit 1; \ + fi + @REPO_DIR="$(shell pwd)"; \ + if ! distrobox list | grep -q "$(DISTROBOX_NAME)"; then \ + echo "Creating distrobox '$(DISTROBOX_NAME)'..."; \ + distrobox create --name $(DISTROBOX_NAME) --image $(DISTROBOX_IMAGE) --volume /var/run/docker.sock:/var/run/docker.sock; \ + echo "Distrobox created."; \ + fi; \ + echo "Installing dependencies..."; \ + distrobox enter --name $(DISTROBOX_NAME) -- /bin/sh -c "cd $$REPO_DIR && .dev/setup.sh" + @echo "" + @# Step 3: Setup pre-commit hook + @echo "$(BLUE)Setting up pre-commit hook...$(NC)" + @ln -sf "$(shell pwd)/.dev/pre-commit.sh" "$(shell pwd)/.git/hooks/pre-commit" 2>/dev/null || echo "Note: Could not create pre-commit hook" + @echo "" + @echo "$(GREEN)Development environment ready!$(NC)" + @echo "" + @echo "To start OpenCode, run:" + @echo " $(YELLOW)make agent$(NC)" + +agent: ## Enter distrobox and run OpenCode interactively + @echo "$(BLUE)Starting OpenCode in distrobox...$(NC)" + @if ! distrobox list | grep -q "$(DISTROBOX_NAME)"; then \ + echo "$(RED)Distrobox '$(DISTROBOX_NAME)' does not exist. Run 'make dev' first.$(NC)"; \ + exit 1; \ + fi + @REPO_DIR="$(shell pwd)"; \ + echo "Entering distrobox and starting OpenCode..."; \ + echo "$(GREEN)Distrobox will open with OpenCode. Your host is protected!$(NC)"; \ + distrobox enter --name $(DISTROBOX_NAME) -- /bin/sh -c "cd $$REPO_DIR && export PATH=\"\$$HOME/.opencode/bin:\$$PATH\" && exec opencode web" + +agent-stop: ## Stop OpenCode in distrobox + @echo "$(BLUE)Stopping OpenCode...$(NC)" + @distrobox enter --name $(DISTROBOX_NAME) -- pkill -f "opencode" 2>/dev/null || echo "No opencode process found" + ##@ Development (ENVIRONMENT=dev) up: ## Start all services in development mode diff --git a/documentation/dev.md b/documentation/dev.md new file mode 100644 index 00000000..7aee6042 --- /dev/null +++ b/documentation/dev.md @@ -0,0 +1,37 @@ +# Getting Started + +## Prerequisites + +- distrobox (`pipx install distrobox`) +- Git + +## Quick Start + +- Follow the getting started guide + +- Set up the dev environment +```bash +make dev +``` + +- Run the opencode agent +```bash +make agent +``` + +### Make Commands + +| Command | Description | +|---------|-------------| +| `make dev` | Setup dev environment (distrobox + agency-agents + git hooks) | +| `make agent` | Start OpenCode in distrobox | +| `make test` | Run all tests (API + Frontend) | +| `make help` | Show available commands | + +## Health Check + +Check API and database health: +```bash +curl http://localhost:8080/health/ready +# Returns: {"checks":{},"status":"ok"} +``` diff --git a/documentation/getting-started.md b/documentation/getting-started.md index 775d5125..a1b8ffdc 100644 --- a/documentation/getting-started.md +++ b/documentation/getting-started.md @@ -1,21 +1,23 @@ # Getting Started +## Prerequisites + +- Docker or Podman + ## Quick Start +- Clone the repo ```bash -# Clone the repository git clone https://github.com/jayfalls/ace_prototype.git cd ace_prototype +``` -# Start all services +- Run the ACE +```bash make up ``` -## Configuration - -Copy `.env.example` to `.env` if you want to customize any settings. - -## Make Commands +### Make Commands | Command | Description | |---------|-------------| @@ -30,7 +32,6 @@ Copy `.env.example` to `.env` if you want to customize any settings. | `make clean` | Remove all containers and volumes | | `make build` | Build all images | | `make ps` | Show running containers | -| `make test` | Run all tests (API + Frontend) | | `make help` | Show available commands | ## Services @@ -41,11 +42,3 @@ Copy `.env.example` to `.env` if you want to customize any settings. | API | http://localhost:8080 | | PostgreSQL | localhost:5432 | | NATS | localhost:4222 | - -## Health Check - -Check API and database health: -```bash -curl http://localhost:8080/health -# Returns: {"status":"OK","db":"healthy"} -``` From 374ab49c02d340b0d7310e93cc0975ecb7fe4c75 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 15 Mar 2026 18:57:41 +0200 Subject: [PATCH 02/32] removed openhands config --- .openhands/pre-commit.sh | 275 ------------------------------------ .openhands/setup.sh | 294 --------------------------------------- 2 files changed, 569 deletions(-) delete mode 100755 .openhands/pre-commit.sh delete mode 100755 .openhands/setup.sh diff --git a/.openhands/pre-commit.sh b/.openhands/pre-commit.sh deleted file mode 100755 index f68b6fa2..00000000 --- a/.openhands/pre-commit.sh +++ /dev/null @@ -1,275 +0,0 @@ -#!/bin/bash -# -# .openhands/pre-commit.sh -# -# Quality gates that run before every commit to enforce code quality. -# This script should be run before committing to ensure all quality checks pass. -# - -set +euo pipefail - -# Get the directory where this script is located -# Resolve symlinks to get the actual script location (handles git hook symlink case) -SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || echo "${BASH_SOURCE[0]}")" -SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Add Go bin to PATH -export PATH="$HOME/go/bin:$HOME/.local/bin:$PATH" - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Track if we're in a git repository -IS_GIT_REPO=false -if [ -d "$REPO_ROOT/.git" ]; then - IS_GIT_REPO=true -fi - -log_info() { - echo -e "${BLUE}[PRE-COMMIT]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[PASS]${NC} $1" -} - -log_fail() { - echo -e "${RED}[FAIL]${NC} $1" -} - -log_skip() { - echo -e "${YELLOW}[SKIP]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Change to repo root -cd "$REPO_ROOT" - -# Track overall status -FAILED=0 -SKIPPED=0 - -echo "" -echo "==========================================" -echo " OpenHands Pre-Commit Quality Gates" -echo "==========================================" -echo "" - -# ============================================ -# 1. Go Build Verification -# ============================================ -log_info "1/4: Go Build Verification..." - -cd "$REPO_ROOT/backend" - -# Check if go.work exists -if [ ! -f "go.work" ]; then - log_skip "No Go workspace found, skipping build verification" - ((SKIPPED++)) -else - # Build all modules in the workspace individually - BUILD_SUCCESS=true - BUILD_WARNINGS=false - for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do - if [ -d "$module" ] && [ -f "$module/go.mod" ]; then - log_info "Building $module..." - BUILD_OUTPUT=$(cd "$module" && go build ./... 2>&1) - if [ $? -ne 0 ]; then - # Check if this is a pre-existing issue (not introduced by recent changes) - log_warn "Build issue in $module (may be pre-existing):" - echo "$BUILD_OUTPUT" | head -5 - BUILD_WARNINGS=true - fi - fi - done - - if [ "$BUILD_WARNINGS" = true ]; then - log_warn "Build verification had warnings (pre-existing issues detected)" - fi - log_success "Go build verification complete" -fi - -echo "" - -# ============================================ -# 2. SQLC Generate Validation -# ============================================ -log_info "2/4: SQLC Generate Validation..." - -cd "$REPO_ROOT/backend" - -# Track if any sqlc.yaml files exist -SQLC_EXISTS=false -SQLC_FAILED=false - -# Check each module in the workspace -for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do - if [ -d "$module" ] && [ -f "$module/sqlc.yaml" ]; then - SQLC_EXISTS=true - log_info "Running sqlc generate for $module..." - - # Save current generated files for comparison - if [ -d "$module/sqlc" ]; then - TEMP_DIR=$(mktemp -d) - cp -r "$module/sqlc" "$TEMP_DIR/sqlc_backup" - - # Generate new files - if (cd "$module" && sqlc generate 2>&1); then - # Compare to see if anything changed - if diff -rq "$TEMP_DIR/sqlc_backup" "$module/sqlc" > /dev/null 2>&1; then - log_success "sqlc generate for $module - no changes needed" - else - log_warn "sqlc generate for $module - generated files are out of date" - log_info "Run 'sqlc generate' in $module to update generated files" - fi - - # Clean up - rm -rf "$TEMP_DIR" - else - log_warn "sqlc generate for $module had issues (may be pre-existing)" - fi - else - # No existing generated files, just run generate - if (cd "$module" && sqlc generate 2>&1); then - log_success "sqlc generate for $module - generated successfully" - else - log_warn "sqlc generate for $module had issues (may be pre-existing)" - fi - fi - fi -done - -if [ "$SQLC_EXISTS" = false ]; then - log_skip "No sqlc.yaml files found, skipping SQLC validation" - ((SKIPPED++)) -elif ! command -v sqlc &> /dev/null; then - log_skip "sqlc not installed, skipping SQLC validation" - ((SKIPPED++)) -else - log_success "SQLC validation complete" -fi - -echo "" - -# ============================================ -# 3. Go Test Suite -# ============================================ -log_info "3/4: Go Test Suite..." - -cd "$REPO_ROOT/backend" - -# Check if go.work exists -if [ ! -f "go.work" ]; then - log_skip "No Go workspace found, skipping test suite" - ((SKIPPED++)) -else - # Test all modules in the workspace individually - TEST_SUCCESS=true - for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do - if [ -d "$module" ] && [ -f "$module/go.mod" ]; then - if find "$module" -name "*_test.go" -type f 2>/dev/null | grep -q .; then - log_info "Testing $module..." - if ! (cd "$module" && go test -v ./...) 2>&1; then - log_warn "Tests failed or had issues in $module" - fi - fi - fi - done - - log_success "Go test suite complete" -fi - -echo "" - -# ============================================ -# 4. Frontend Lint (svelte-check) -# ============================================ -log_info "4/4: Frontend Lint..." - -cd "$REPO_ROOT/frontend" - -if [ -f "package.json" ]; then - # Check if svelte-kit is set up (need .svelte-kit directory) - if [ -d ".svelte-kit" ]; then - # Run svelte-check for TypeScript and Svelte validation - if npx svelte-check --threshold warning 2>&1; then - log_success "Frontend lint passed" - else - log_warn "Frontend lint had warnings" - fi - elif [ -d "node_modules" ]; then - log_info "SvelteKit not initialized, running svelte-kit sync..." - if npx svelte-kit sync 2>&1; then - log_success "SvelteKit sync complete" - if npx svelte-check --threshold warning 2>&1; then - log_success "Frontend lint passed" - else - log_warn "Frontend lint had warnings" - fi - else - log_skip "SvelteKit setup incomplete, skipping frontend lint" - ((SKIPPED++)) - fi - else - log_skip "No node_modules found, skipping frontend lint" - ((SKIPPED++)) - fi -else - log_skip "No frontend package.json found, skipping lint" - ((SKIPPED++)) -fi - -echo "" - -# ============================================ -# Summary -# ============================================ -echo "==========================================" -echo " Pre-Commit Quality Gates Summary" -echo "==========================================" -echo "" - -# Count warnings -WARNINGS=0 -if [ -n "${BUILD_WARNINGS:-}" ] && [ "$BUILD_WARNINGS" = true ]; then - ((WARNINGS++)) -fi - -if [ $FAILED -gt 0 ]; then - echo -e "${RED}$FAILED quality gate(s) FAILED${NC}" - echo "" - echo "Please fix the failing checks before committing." - echo "" - exit 1 -elif [ $WARNINGS -gt 0 ]; then - echo -e "${YELLOW}Quality gates completed with warnings${NC}" - echo "" - echo "Warnings indicate pre-existing issues or configuration problems." - echo "Review the output above for details." - echo "" - exit 0 -elif [ $SKIPPED -gt 0 ]; then - echo -e "${GREEN}All quality gates passed (or skipped)${NC}" - echo "" - echo "Passed: $((4 - SKIPPED - FAILED))" - echo "Skipped: $SKIPPED" - echo "Failed: $FAILED" - echo "" - exit 0 -else - echo -e "${GREEN}All quality gates PASSED!${NC}" - echo "" - exit 0 -fi diff --git a/.openhands/setup.sh b/.openhands/setup.sh deleted file mode 100755 index 363a3b9d..00000000 --- a/.openhands/setup.sh +++ /dev/null @@ -1,294 +0,0 @@ -#!/bin/bash -# -# .openhands/setup.sh -# -# This script runs automatically every time OpenHands begins working with the repository. -# It ensures the environment is correct before any agent does any work. -# -# This script is IDEMPOTENT - safe to run multiple times without side effects. -# - -set -euo pipefail - -# Get the directory where this script is located (repo root) -# Resolve symlinks to handle git hook symlink case -SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || echo "${BASH_SOURCE[0]}")" -SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Configuration -AGENCY_AGENTS_REPO="https://github.com/msitarzewski/agency-agents.git" -AGENCY_AGENTS_DIR="$REPO_ROOT/agency-agents" -GOPATH="${GOPATH:-$HOME/go}" -PATH_ADDITIONS="$GOPATH/bin:$HOME/.local/bin" - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -log_info() { - echo -e "${BLUE}[SETUP]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SETUP]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[SETUP]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Add PATH additions -export PATH="$PATH_ADDITIONS:$PATH" - -# ============================================ -# 0. Install Required Tools (if missing) -# ============================================ - -# Install Go -if ! command -v go &> /dev/null; then - log_info "Installing Go..." - sudo apt-get update && sudo apt-get install -y golang-go -else - log_success "Go already installed" -fi - -# Install Node.js and npm -if ! command -v node &> /dev/null; then - log_info "Installing Node.js and npm..." - sudo apt-get update && sudo apt-get install -y nodejs npm -else - log_success "Node.js already installed" -fi - -# Install Docker (if not installed) -if ! command -v docker &> /dev/null; then - log_info "Installing Docker..." - sudo apt-get update && sudo apt-get install -y docker.io -fi - -# Start Docker daemon if not running -if ! docker info &> /dev/null 2>&1; then - log_info "Starting Docker daemon..." - sudo dockerd > /tmp/docker.log 2>&1 & - sleep 5 -else - log_success "Docker is running" -fi - -log_success "Required tools installed" - -# ============================================ -# 1. Clone agency-agents (if not already present) -# ============================================ -log_info "Checking agency-agents repository..." - -if [ -d "$AGENCY_AGENTS_DIR" ]; then - log_success "agency-agents already exists at $AGENCY_AGENTS_DIR" - - # Verify it's a git repo and has the correct remote - if [ -d "$AGENCY_AGENTS_DIR/.git" ]; then - cd "$AGENCY_AGENTS_DIR" - CURRENT_REMOTE=$(git remote get-url origin 2>/dev/null || echo "") - if [ "$CURRENT_REMOTE" != "$AGENCY_AGENTS_REPO" ]; then - log_warn "Remote URL mismatch. Updating to correct repository..." - git remote set-url origin "$AGENCY_AGENTS_REPO" - git fetch origin - fi - else - log_warn "Directory exists but is not a git repo. Removing and re-cloning..." - rm -rf "$AGENCY_AGENTS_DIR" - git clone --depth 1 "$AGENCY_AGENTS_REPO" "$AGENCY_AGENTS_DIR" - fi -else - log_info "Cloning agency-agents repository..." - git clone --depth 1 "$AGENCY_AGENTS_REPO" "$AGENCY_AGENTS_DIR" - log_success "agency-agents cloned successfully" -fi - -# ============================================ -# 2. Install Go dependencies for all modules -# ============================================ -log_info "Installing Go workspace dependencies..." - -cd "$REPO_ROOT/backend" - -# Verify Go workspace is set up -if [ ! -f "go.work" ]; then - log_error "Go workspace file not found at $REPO_ROOT/backend/go.work" - exit 1 -fi - -# Download dependencies for all modules in the workspace -go work sync -go mod download -x - -# Download dependencies for each module explicitly -for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do - if [ -d "$module" ] && [ -f "$module/go.mod" ]; then - log_info "Installing dependencies for $module..." - (cd "$module" && go mod download -x) - fi -done - -log_success "Go dependencies installed" - -# ============================================ -# 3. Install global Go tooling -# ============================================ -log_info "Installing global Go tooling..." - -# Install sqlc -if ! command -v sqlc &> /dev/null; then - log_info "Installing sqlc..." - go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest -else - log_success "sqlc already installed" -fi - -# Install goose CLI -if ! command -v goose &> /dev/null; then - log_info "Installing goose..." - go install github.com/pressly/goose/cmd/goose@latest -else - log_success "goose already installed" -fi - -# Install air for hot reload -if ! command -v air &> /dev/null; then - log_info "Installing air..." - go install github.com/air-verse/air@latest -else - log_success "air already installed" -fi - -# Verify installations -log_info "Verifying tool installations..." -command -v sqlc >/dev/null 2>&1 || { log_error "sqlc installation failed"; exit 1; } -command -v goose >/dev/null 2>&1 || { log_error "goose installation failed"; exit 1; } -command -v air >/dev/null 2>&1 || { log_error "air installation failed"; exit 1; } - -log_success "Global Go tooling installed" - -# ============================================ -# 4. Install frontend Node dependencies -# ============================================ -log_info "Installing frontend Node dependencies..." - -cd "$REPO_ROOT/frontend" - -if [ -f "package.json" ]; then - # Check if node_modules already exists - if [ -d "node_modules" ]; then - log_success "node_modules already exists, running npm install to ensure consistency..." - npm install - else - log_info "Running npm install..." - npm install - fi - - # Check if svelte-check is available for linting - if ! npx svelte-check --version &> /dev/null; then - log_info "Installing svelte-check..." - npm install - fi - - log_success "Frontend dependencies installed" -else - log_error "package.json not found in frontend directory" - exit 1 -fi - -# ============================================ -# 5. Set up Git Pre-commit Hook -# ============================================ -log_info "Setting up Git pre-commit hook..." - -HOOKS_DIR="$REPO_ROOT/.git/hooks" -PRECOMMIT_HOOK="$HOOKS_DIR/pre-commit" -SCRIPT_HOOK="$REPO_ROOT/.openhands/pre-commit.sh" - -# Ensure hooks directory exists -mkdir -p "$HOOKS_DIR" - -# Create the pre-commit hook if it doesn't exist or points to a different script -if [ -L "$PRECOMMIT_HOOK" ]; then - CURRENT_TARGET=$(readlink -f "$PRECOMMIT_HOOK" 2>/dev/null || echo "") - if [ "$CURRENT_TARGET" = "$SCRIPT_HOOK" ]; then - log_success "Pre-commit hook already configured" - else - log_info "Updating pre-commit hook..." - rm "$PRECOMMIT_HOOK" - ln -s "$SCRIPT_HOOK" "$PRECOMMIT_HOOK" - log_success "Pre-commit hook updated" - fi -elif [ -f "$PRECOMMIT_HOOK" ]; then - log_warn "Pre-commit hook already exists (not a symlink). Backing up and replacing..." - mv "$PRECOMMIT_HOOK" "${PRECOMMIT_HOOK}.backup" - ln -s "$SCRIPT_HOOK" "$PRECOMMIT_HOOK" - log_success "Pre-commit hook installed (backup at ${PRECOMMIT_HOOK}.backup)" -else - ln -s "$SCRIPT_HOOK" "$PRECOMMIT_HOOK" - log_success "Pre-commit hook installed" -fi - -# ============================================ -# 6. Set environment variables -# ============================================ -log_info "Setting up environment variables..." - -# Create .env file from example if it doesn't exist -if [ -f "$REPO_ROOT/.env.example" ] && [ ! -f "$REPO_ROOT/.env" ]; then - log_info "Creating .env from .env.example..." - cp "$REPO_ROOT/.env.example" "$REPO_ROOT/.env" -fi - -# Ensure PATH includes Go bin -GOBIN_PATH="$GOPATH/bin" -if [[ ":$PATH:" != *":$GOBIN_PATH:"* ]]; then - log_info "Adding $GOBIN_PATH to PATH in profile..." - echo "" >> "$HOME/.bashrc" - echo "# Added by .openhands/setup.sh" >> "$HOME/.bashrc" - echo "export PATH=\"\$PATH:$GOBIN_PATH\"" >> "$HOME/.bashrc" -fi - -# Export for current session -export PATH="$GOBIN_PATH:$PATH" - -log_success "Environment setup complete" - -# ============================================ -# 6. Final verification -# ============================================ -log_info "Running final verification..." - -cd "$REPO_ROOT" - -# Verify Go builds -log_info "Verifying Go build..." -if go build ./... 2>/dev/null; then - log_success "Go build verified" -else - log_warn "Go build verification had warnings (this may be normal for empty modules)" -fi - -# Verify sqlc generate works (if sqlc.yaml exists) -cd "$REPO_ROOT/backend" -for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do - if [ -d "$module" ] && [ -f "$module/sqlc.yaml" ]; then - log_info "Running sqlc generate for $module..." - (cd "$module" && sqlc generate 2>/dev/null || true) - fi -done - -log_success "Setup complete!" -log_info "Environment is ready for OpenHands agents to work." - -exit 0 From 76e197aa90deec1e8ef4defeca3e0f2494eb4520 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 15 Mar 2026 19:54:39 +0200 Subject: [PATCH 03/32] feat: overhaul orchestrator with per-unit memory and bespoke agents [unit: opencode-integration] - Add per-unit short-term memory in .agents/memory/short-term/ - Split planning into bespoke agents (discovery, requirements) - Add all sub-agents with agency-agents references - Add QA agent for quality checks after each subagent - Update memory encoding (episodic/semantic) - Add unit reference guidance for GitHub PRs/issues --- .agents/memory/long_term.json | 11 + .../short-term/opencode-integration.json | 20 ++ .dev/{setup.sh => distrobox-setup.sh} | 0 .opencode/agents/architecture.md | 71 ++++ .opencode/agents/backend.md | 61 ++++ .opencode/agents/frontend.md | 56 +++ .opencode/agents/implementation.md | 83 +++-- .opencode/agents/orchestrator.md | 332 ++++++++++++++++-- .opencode/agents/planning-discovery.md | 55 +++ .opencode/agents/planning-requirements.md | 62 ++++ .opencode/agents/planning.md | 50 --- .opencode/agents/qa.md | 101 ++++++ .opencode/agents/research.md | 74 ++-- .opencode/agents/review.md | 64 ++-- .opencode/agents/tester.md | 39 +- .opencode/agents/testing.md | 64 ++++ AGENTS.md | 41 --- Makefile | 2 +- 18 files changed, 957 insertions(+), 229 deletions(-) create mode 100644 .agents/memory/long_term.json create mode 100644 .agents/memory/short-term/opencode-integration.json rename .dev/{setup.sh => distrobox-setup.sh} (100%) create mode 100644 .opencode/agents/architecture.md create mode 100644 .opencode/agents/backend.md create mode 100644 .opencode/agents/frontend.md create mode 100644 .opencode/agents/planning-discovery.md create mode 100644 .opencode/agents/planning-requirements.md delete mode 100644 .opencode/agents/planning.md create mode 100644 .opencode/agents/qa.md create mode 100644 .opencode/agents/testing.md diff --git a/.agents/memory/long_term.json b/.agents/memory/long_term.json new file mode 100644 index 00000000..51617bb1 --- /dev/null +++ b/.agents/memory/long_term.json @@ -0,0 +1,11 @@ +{ + "version": "1.0", + "completed_units": {}, + "preferences": { + "retry_count": 3, + "auto_approve_github_issues": false + }, + "agent_performance": {}, + "learned_patterns": [], + "last_sync": "" +} diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json new file mode 100644 index 00000000..63619f93 --- /dev/null +++ b/.agents/memory/short-term/opencode-integration.json @@ -0,0 +1,20 @@ +{ + "unit": "opencode-integration", + "current_phase": "completed", + "status": "completed", + "completed_phases": [ + "planning-discovery", + "planning-requirements", + "research", + "architecture", + "implementation", + "testing", + "backend", + "frontend", + "review", + "tester" + ], + "pending_tasks": [], + "trigger_context": "user_request", + "last_updated": "2026-03-15T18:00:00Z" +} diff --git a/.dev/setup.sh b/.dev/distrobox-setup.sh similarity index 100% rename from .dev/setup.sh rename to .dev/distrobox-setup.sh diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md new file mode 100644 index 00000000..ed065b6c --- /dev/null +++ b/.opencode/agents/architecture.md @@ -0,0 +1,71 @@ +--- +description: Architecture - system design, API specs, and observability +mode: subagent +--- + +# Architecture Agent + +Handles technical architecture, API specifications, and observability. + +## Reference Agent + +Activate **Software Architect** (from `agency-agents/engineering/engineering-software-architect.md`) + +## Your Task + +Create technical architecture documents for a unit. + +## Context + +- Read `design/units/{UNIT_NAME}/research.md` first +- Read `design/units/{UNIT_NAME}/fsd.md` +- Read `design/units/{UNIT_NAME}/dependencies.md` +- Read `design/README.md` for ACE Framework patterns +- Unit directory: `design/units/{UNIT_NAME}/` + +## Documents Created + +### 1. Architecture (architecture.md) +- System components +- Data flow diagrams +- Integration points +- Component responsibilities +- Scalability considerations + +### 2. API Specifications (api.md) +- REST endpoints +- Request/response schemas +- Authentication/authorization +- Error responses +- Rate limiting + +### 3. Monitoring (monitoring.md) +- Metrics to collect +- Logging strategy +- Alert definitions +- Dashboards + +## Templates + +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/architecture.md` +- `.agents/skills/unit-planning/unit-templates/api.md` +- `.agents/skills/unit-planning/unit-templates/monitoring.md` + +## Prerequisites + +- `research.md` must exist +- `dependencies.md` must exist +- `fsd.md` must exist + +## Output + +Create in `design/units/{UNIT_NAME}/`: +- `architecture.md` +- `api.md` +- `monitoring.md` + +Return file paths and architecture summary. diff --git a/.opencode/agents/backend.md b/.opencode/agents/backend.md new file mode 100644 index 00000000..dde508c3 --- /dev/null +++ b/.opencode/agents/backend.md @@ -0,0 +1,61 @@ +--- +description: Backend code implementation - Go backend development +mode: subagent +--- + +# Backend Implementation Agent + +You implement backend code based on the architecture and implementation plans. + +## Reference Agent + +Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) + +## Your Task + +Implement backend code for the unit specified by the orchestrator. + +## Context + +- Read `design/units/{UNIT_NAME}/implementation.md` first +- Read `design/units/{UNIT_NAME}/architecture.md` +- Read `design/units/{UNIT_NAME}/api.md` +- Read `design/units/{UNIT_NAME}/fsd.md` +- Read `design/README.md` for ACE Framework patterns +- Read `AGENTS.md` for coding best practices + +## Workflow + +### 1. Preparation +- Review the micro-PR breakdown from `implementation.md` +- Understand API contracts from `api.md` +- Review data models from `fsd.md` + +### 2. Implementation +Follow the micro-PR breakdown. Each PR should: +- Be independently testable +- Have clear acceptance criteria +- Include necessary tests + +### 3. Code Standards (from AGENTS.md) + +#### Go Backend Requirements +- **Error Handling**: Always handle errors, never ignore with `_` +- **Naming**: + - Variables: camelCase + - Types/Exports: PascalCase + - Constants: PascalCase or SCREAMING_SNAKE_CASE +- **Database**: Use SQLC for type-safe database access (no raw SQL queries) +- **Context**: Use context.Context for request-scoped values and cancellation +- **Migrations**: Write all migrations in Go directly using Goose +- **Layered Architecture**: Always use Handler → Service → Repository pattern + +### 4. Testing +- Write unit tests (aim for 80% coverage) +- Write integration tests for API endpoints + +## Output + +- Implemented code in `backend/` +- Tests in appropriate test files +- Summary of what was implemented and which PRs diff --git a/.opencode/agents/frontend.md b/.opencode/agents/frontend.md new file mode 100644 index 00000000..c9bd14fd --- /dev/null +++ b/.opencode/agents/frontend.md @@ -0,0 +1,56 @@ +--- +description: Frontend code implementation - SvelteKit frontend development +mode: subagent +--- + +# Frontend Implementation Agent + +You implement frontend code based on the architecture and implementation plans. + +## Reference Agent + +Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) + +## Your Task + +Implement frontend code for the unit specified by the orchestrator. + +## Context + +- Read `design/units/{UNIT_NAME}/implementation.md` first +- Read `design/units/{UNIT_NAME}/architecture.md` +- Read `design/units/{UNIT_NAME}/api.md` +- Read `design/units/{UNIT_NAME}/mockups.md` +- Read `design/units/{UNIT_NAME}/fsd.md` +- Read `design/README.md` for ACE Framework patterns +- Read `AGENTS.md` for coding best practices + +## Workflow + +### 1. Preparation +- Review the micro-PR breakdown from `implementation.md` +- Understand API contracts from `api.md` +- Review UI mockups from `mockups.md` + +### 2. Implementation +Follow the micro-PR breakdown. Each PR should: +- Be independently testable +- Have clear acceptance criteria +- Include necessary tests + +### 3. Code Standards (from AGENTS.md) + +#### TypeScript/SvelteKit Frontend Requirements +- **Prefer**: Use interfaces over types where possible +- **Svelte 5**: Use runes syntax (`$state`, `$derived`, `$effect`) +- **Components**: Keep components small and focused on single responsibilities + +### 4. Testing +- Write unit tests for components using Vitest +- Write integration tests for critical user flows + +## Output + +- Implemented code in `frontend/` +- Tests in appropriate test files +- Summary of what was implemented and which PRs diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 1c195157..9173c34d 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -1,52 +1,77 @@ --- -description: Unit implementation - architecture and implementation planning +description: Implementation planning - micro-PRs, security, and migrations mode: subagent --- -# Unit Implementation Agent +# Implementation Agent -Activate the **Backend Architect** (from `agency-agents/engineering/engineering-backend-architect.md`) -Also read `design/README.md` for ACE-specific patterns. +Handles implementation planning, security, and database migrations. + +## Reference Agent + +Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) ## Your Task -Complete the implementation planning phase for the unit specified by the user. +Create implementation plan with micro-PR breakdown for a unit. ## Context -- Read ALL planning documents in `design/units/{UNIT_NAME}/` first +- Read `design/units/{UNIT_NAME}/architecture.md` first +- Read `design/units/{UNIT_NAME}/api.md` +- Read `design/units/{UNIT_NAME}/fsd.md` - Read `design/README.md` for ACE Framework patterns +- Unit directory: `design/units/{UNIT_NAME}/` -## Workflow - -### 1. Architecture Design -Create `architecture.md`: -- System components -- Data flow -- Integration points +## Documents Created -### 2. Implementation Plan -Create `implementation.md`: +### 1. Implementation Plan (implementation.md) - Breakdown into micro-PRs -- Each PR should be independently testable -- Include acceptance criteria +- Each PR independently testable +- PR ordering and dependencies +- Acceptance criteria per PR +- Task breakdown -### 3. Security -Create `security.md` +### 2. Security (security.md) +- Security considerations +- Authentication/authorization +- Data protection +- Vulnerability prevention -### 4. Additional Documents as needed -- `api.md` - API specifications -- `migration_and_rollback.md` - Database migrations -- `monitoring.md` - Observability requirements +### 3. Migration and Rollback (migration_and_rollback.md) +- Database migrations +- Rollback procedures +- Data migration scripts +- Zero-downtime strategy ## Templates -Use templates from `.agents/skills/unit-workflow/unit-templates/`: -- `architecture.md` -- `implementation.md` -- `security.md` +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/implementation.md` +- `.agents/skills/unit-planning/unit-templates/security.md` +- `.agents/skills/unit-planning/unit-templates/migration_and_rollback.md` + +## Prerequisites + +- `architecture.md` must exist +- `api.md` must exist + +## Micro-PR Guidelines + +Each micro-PR should: +- Be independently testable +- Have clear acceptance criteria +- Include necessary tests +- Be reviewable in one sitting ## Output -Create all documents in `design/units/{UNIT_NAME}/` -Return the implementation breakdown with micro-PRs suggested. +Create in `design/units/{UNIT_NAME}/`: +- `implementation.md` +- `security.md` +- `migration_and_rollback.md` + +Return file paths and micro-PR breakdown. diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 5193192d..1f57655e 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -1,52 +1,316 @@ --- -description: Orchestrates the full unit workflow across planning, research, implementation, and review -mode: subagent +description: Orchestrates the full unit workflow across planning, research, implementation, and review - delegates ALL work to subagents +mode: primary --- # Unit Workflow Orchestrator -You orchestrate the complete ACE Framework unit workflow by delegating to specialized subagents. +You are the central coordinator for the ACE Framework. **You never do work directly - you always delegate to specialized subagents.** + +## Core Principle: Always Delegate + +**NEVER write code, create documents, or perform tasks directly.** Your role is to: +1. Understand what the user wants +2. Delegate to the appropriate subagent +3. Run QA after each subagent completes +4. Report results back to the user + +## Memory System + +You have access to memory stores in `.agents/memory/`: + +### Short-term Memory - Per-Unit Files +Each unit has its own file: `.agents/memory/short-term/{unit-name}.json` + +Example: `.agents/memory/short-term/observability.json` + +Structure: +```json +{ + "unit": "observability", + "current_phase": "planning-discovery", + "status": "in_progress", + "completed_phases": [], + "pending_tasks": [], + "trigger_context": "user_request", + "last_updated": "2026-03-15T12:00:00Z" +} +``` + +**How to find the right memory file:** +1. If user specifies unit → Load `.agents/memory/short-term/{unit}.json` +2. If GitHub event → Extract issue/PR number, find unit from branch name or context +3. If new session → Ask user which unit they're working on + +### Long-term Memory (`long_term.json`) - Persistent +Location: `.agents/memory/long_term.json` + +Across all sessions: +- `completed_units`: Historical unit completion data +- `preferences`: User preferences +- `agent_performance`: Which agents perform best for what tasks +- `learned_patterns`: Patterns learned from workflows + +### Memory Encoding Principles + +**Keep it Lean**: +- Only store essential state +- Delete completed tasks promptly +- Prune old events after phase completion + +**Episodic Memory**: +- Store significant events as episodes +- Format: `{ "episode": "start_unit_X", "unit": "X", "phase": "planning", "outcome": "success", "timestamp": "..." }` + +**Semantic Memory**: +- Store learned facts that persist +- Format: `{ "fact": "agent_Y_best_for_research", "confidence": 0.9, "evidence": "..." }` + +### Memory Operations + +**Before every delegation:** +1. Determine unit name from user request or trigger +2. Load `.agents/memory/short-term/{unit}.json` +3. Read long-term memory for preferences and patterns +4. Determine current phase and next steps + +**After every delegation:** +1. Update `.agents/memory/short-term/{unit}.json` with results +2. Extract any semantic learnings to long-term memory +3. Prune completed tasks + +**Loading Unit Memory:** +- User says "work on observability" → Load `short-term/observability.json` +- GitHub event on branch `feature/observability` → Load `short-term/observability.json` +- New unit → Create `short-term/{new-unit}.json` ## Available Subagents -| Subagent | Purpose | -|----------|---------| -| `planning` | Problem space, BSD, user stories | -| `research` | Research, FSD | -| `implementation` | Architecture, implementation plan | -| `review` | Code review | -| `tester` | Runs tests via docker/make | +| Subagent | Purpose | Documents Created | +|----------|---------|-------------------| +| `planning-discovery` | Problem space + BSD | `problem_space.md`, `bsd.md` | +| `planning-requirements` | User stories + FSD | `user_stories.md`, `fsd.md` | +| `research` | Tech evaluation + deps | `research.md`, `dependencies.md` | +| `architecture` | System design + API + monitoring | `architecture.md`, `api.md`, `monitoring.md` | +| `implementation` | Implementation plan + security + migrations | `implementation.md`, `security.md`, `migration_and_rollback.md` | +| `testing` | Testing strategy + mockups | `testing.md`, `mockups.md` | +| `backend` | Go backend code | Code in `backend/` | +| `frontend` | SvelteKit frontend code | Code in `frontend/` | +| `review` | Code review | Review findings | +| `tester` | Run tests via docker/make | Test results | +| `qa` | Quality assurance | QA verdict | -## Workflow +## Workflow Phases + +The standard unit workflow sequence: +1. **planning-discovery** → Problem space, BSD +2. **planning-requirements** → User stories, FSD +3. **research** → Technology research, dependencies +4. **architecture** → Architecture, API, monitoring +5. **implementation** → Implementation plan, security, migrations +6. **testing** → Testing strategy, mockups +7. **backend** → Backend code +8. **frontend** → Frontend code +9. **review** → Code review +10. **tester** → Run tests + +## Trigger Correlation + +When a trigger comes in (GitHub comment, issue, etc.): +1. Parse the trigger (issue number, PR number, keywords) +2. Read short-term memory to find matching unit +3. If no match, check long-term memory for completed units +4. If still no match, ask user which unit this relates to +5. Set `trigger_context` in short-term memory + +### Trigger Types +- **GitHub Issue Comment**: Extract issue number → find unit +- **GitHub PR Comment**: Extract PR number → find unit from branch +- **GitHub Review Comment**: Map to unit being reviewed +- **User Request**: Parse unit name from request +- **New Session**: Resume from short-term memory active units + +## Error Handling & Retry Logic + +### Retry Strategy +- **Max retries**: 3 attempts per subagent task +- **Retry on**: Subagent failures, test failures, review failures + +### Escalation Flow +``` +1. First attempt: Delegate to subagent +2. If fails: Check error type + - Recoverable (timeout, transient): Retry up to 3x + - Non-recoverable (bad input, missing docs): Report to user +3. After 3 retries: Escalate to user with error details +4. User decides: Retry with new input, skip task, or abort +``` + +## QA After Every Subagent + +**CRITICAL**: After EVERY subagent completes, you MUST run the QA subagent to evaluate the work before proceeding. -### Step 1: Understand Current State -1. Read `design/units/` to see existing units -2. If unit exists, read its documents to see what's completed -3. Determine which phase to work on next +### QA Check Process +1. Subagent completes work +2. Delegate to `@qa` subagent with: + - What the subagent was supposed to do + - What was actually delivered + - Quality criteria to check +3. If QA passes → Continue to next phase +4. If QA fails → Request subagent to fix issues -### Step 2: Delegate to Subagent -Use Task tool to invoke the appropriate subagent: -- `@planning` for planning phase -- `@research` for research phase -- `@implementation` for implementation phase -- `@review` for review phase -- `@tester` for running tests +## GitHub Integration -### Step 3: Report Results -Return a summary of what was accomplished and what's next. +### Setup +- OpenCode GitHub App handles identity (appears as `opencode[bot]` on commits/PRs/comments) +- Install at: https://github.com/apps/opencode-agent -## Usage +### CRITICAL: Always Reference the Unit +**Every PR and GitHub issue MUST include the unit name** so the orchestrator can load the correct memory file on new sessions. + +**In PR titles/descriptions:** +``` +[unit: opencode-integration] Add orchestrator memory system +``` + +**In commit messages:** +``` +feat: add memory system [unit: opencode-integration] +``` + +**In GitHub issues:** +``` +[unit: observability] How should we handle log aggregation? +``` + +This allows the orchestrator to: +1. Parse unit from PR/issue/branch +2. Load `.agents/memory/short-term/{unit}.json` +3. Resume work from where it left off + +### Workflow Triggers +- **PR comments**: `/opencode` or `/oc` triggers agent +- **Issue comments**: Can trigger agent +- **PR reviews**: Mention `@opencode` to trigger + +### Automatic Reactions +When you detect GitHub events (via user input or webhook): +1. Parse the unit from PR/issue/branch name +2. Load `.agents/memory/short-term/{unit}.json` +3. Correlate to current phase +4. Delegate to appropriate subagent +5. Post results back to GitHub + +## Telegram Integration (Placeholder) + +Future: Integrate with Telegram for real-time notifications and commands. +- User receives: Task completion, failures, approval requests +- User can send: Commands via Telegram bot + +## Creating New Agents + +When you need to create a new specialized agent: + +### When to Create +- A new type of task emerges that doesn't fit existing agents +- A composite agent becomes too complex and needs splitting +- A pattern is identified that warrants its own agent + +### How to Create +1. Create file in `.opencode/agents/` +2. Use this template: +```markdown +--- +description: [One-line description] +mode: subagent +--- + +# [Agent Name] + +## Reference Agent +Activate [Agency Agent Name] (from `agency-agents/[path]/[file].md`) + +## Your Task +[What this agent does] + +## Context +- Read [prerequisite docs] +- Knows about [relevant files] + +## Workflow +1. [Step 1] +2. [Step 2] + +## Output +[What this agent produces] +``` + +### Guidelines +- Always reference a pre-picked agency-agents md file +- Keep agents focused on a single responsibility +- Include clear prerequisites +- Document expected output + +## Usage Patterns + +### Start New Unit +``` User: "Start the observability unit" -1. Check `design/units/observability/` status -2. Launch `@planning` subagent -3. Report results +1. Check integrations are set up (long_term.json) +2. Read short-term memory for state +3. Read design/units/observability/ to see existing docs +4. If no docs → Launch @planning-discovery +5. Run @qa to evaluate output +6. Update memory with progress +7. Report to user +``` +### Continue Existing Unit +``` User: "Continue the core-api unit" -1. Check `design/units/core-api/` status -2. Launch appropriate subagent for next phase -3. Report results +1. Check integrations are set up +2. Read short-term memory for current phase +3. Read design/units/core-api/ for progress +4. Determine next phase needed +5. Launch appropriate subagent +6. Run @qa to evaluate output +7. Update memory +8. Report to user +``` + +### Handle GitHub Event +``` +User: "There's a comment on issue #42" +1. Check integrations are set up +2. Read issue content +3. Correlate to unit (short-term memory → long-term memory → ask user) +4. Set trigger_context +5. Determine task from comment +6. Delegate to appropriate subagent +7. Run @qa on results +8. Post results to GitHub +9. Update memory +``` + +### Handle Failure +``` +Subagent fails after 3 retries +1. Collect error details and logs +2. Present to user with options: + - Retry with different input + - Skip this task + - Abort entire workflow +3. Wait for user decision +4. Execute chosen path +``` + +## Key Reminders -User: "Run tests for the changes" -1. Launch `@tester` subagent -2. Report results +1. **Always check integrations first** - Don't proceed if not set up +2. **Always delegate** - Never do work directly +3. **Always QA** - Run @qa after every subagent +4. **Always update memory** - Track progress, correlate triggers +5. **Always retry** - Up to 3 times, then escalate +6. **Always confirm with user** - Before major actions like creating GitHub issues +7. **Keep memory lean** - Prune completed, store semantic learnings diff --git a/.opencode/agents/planning-discovery.md b/.opencode/agents/planning-discovery.md new file mode 100644 index 00000000..6c12a5fe --- /dev/null +++ b/.opencode/agents/planning-discovery.md @@ -0,0 +1,55 @@ +--- +description: Planning discovery - problem space exploration and business specification +mode: subagent +--- + +# Planning Discovery Agent + +Handles problem space exploration and business specification. + +## Reference Agent + +Activate **Product Manager** (from `agency-agents/product/product-manager.md`) + +## Your Task + +Explore the problem space and define the business specification for a unit. + +## Context + +- Read `design/README.md` for ACE Framework patterns +- Read `design/units/README.md` to see existing units +- Unit directory: `design/units/{UNIT_NAME}/` + +## Documents Created + +### 1. Problem Space (problem_space.md) +Explore through questions before writing: +- What problem are we solving? +- Who are the users? +- What are success criteria? +- What constraints exist? + +### 2. Business Specification (bsd.md) +Define the business case: +- Business value +- Success metrics (measurable) +- Scope definition +- Dependencies + +## Templates + +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/problem_space.md` +- `.agents/skills/unit-planning/unit-templates/bsd.md` + +## Output + +Create in `design/units/{UNIT_NAME}/`: +- `problem_space.md` +- `bsd.md` + +Return file paths and any pending questions for the user. diff --git a/.opencode/agents/planning-requirements.md b/.opencode/agents/planning-requirements.md new file mode 100644 index 00000000..64324193 --- /dev/null +++ b/.opencode/agents/planning-requirements.md @@ -0,0 +1,62 @@ +--- +description: Planning requirements - user stories and functional specification +mode: subagent +--- + +# Planning Requirements Agent + +Handles user stories and functional specification documents. + +## Reference Agent + +Activate **Product Manager** (from `agency-agents/product/product-manager.md`) +Activate **Sprint Prioritizer** (from `agency-agents/product/product-sprint-prioritizer.md`) + +## Your Task + +Define user requirements and functional specifications for a unit. + +## Context + +- Read `design/units/{UNIT_NAME}/problem_space.md` first +- Read `design/units/{UNIT_NAME}/bsd.md` +- Read `design/README.md` for ACE Framework patterns +- Unit directory: `design/units/{UNIT_NAME}/` + +## Documents Created + +### 1. User Stories (user_stories.md) +Capture user requirements with acceptance criteria: +- Format: As a [user], I want [feature], so that [benefit] +- Each story has clear, testable acceptance criteria +- Prioritize stories + +### 2. Functional Specification (fsd.md) +Define functional requirements: +- Functional requirements +- API contracts +- Data models +- Edge cases +- User flows + +## Templates + +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/user_stories.md` +- `.agents/skills/unit-planning/unit-templates/fsd.md` + +## Prerequisites + +- `problem_space.md` must exist +- `bsd.md` must exist + +## Output + +Create in `design/units/{UNIT_NAME}/`: +- `user_stories.md` +- `fsd.md` + +Return file paths and verification that prerequisites are met. diff --git a/.opencode/agents/planning.md b/.opencode/agents/planning.md deleted file mode 100644 index e301885a..00000000 --- a/.opencode/agents/planning.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -description: Unit planning - problem space, BSD, and user stories -mode: subagent ---- - -# Unit Planning Agent - -Activate the **Sprint Prioritizer** (from `agency-agents/product/product-sprint-prioritizer.md`) - -## Your Task - -Complete the planning phase for the unit specified by the user. - -## Context - -- Read `design/README.md` for ACE Framework patterns -- Read `design/units/README.md` to see existing units -- Unit directory: `design/units/{UNIT_NAME}/` - -## Workflow - -### 1. Problem Space Discovery -Before any document writing, explore the problem through questions: -- What problem are we solving? -- Who are the users? -- What are success criteria? -- What constraints exist? - -Ask clarifying questions until problem space is fully understood. Document in `problem_space.md`. - -### 2. Business Specification (BSD) -Define the business case in `bsd.md`: -- Business value -- Success metrics -- Scope definition -- Dependencies - -### 3. User Stories -Capture user requirements in `user_stories.md` with acceptance criteria. - -## Templates - -Use templates from `.agents/skills/unit-workflow/unit-templates/`: -- `bsd.md` -- `user_stories.md` - -## Output - -Create all documents in `design/units/{UNIT_NAME}/` -Return the file paths created and any questions that need user input. diff --git a/.opencode/agents/qa.md b/.opencode/agents/qa.md new file mode 100644 index 00000000..dd90f7ff --- /dev/null +++ b/.opencode/agents/qa.md @@ -0,0 +1,101 @@ +--- +description: Quality assurance agent - evaluates work after every subagent completes +mode: subagent +--- + +# QA Agent + +You evaluate the quality of work produced by other subagents. + +## Reference Agent + +Activate **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) + +## Your Role + +After every subagent completes, you MUST evaluate their work. The orchestrator will delegate to you with: +1. What the subagent was supposed to deliver +2. What was actually delivered +3. Quality criteria to check + +## Evaluation Criteria + +### General Quality Gates +- [ ] Task completed as requested +- [ ] No syntax errors or obvious bugs +- [ ] Follows ACE Framework patterns (from `design/README.md`) +- [ ] Documentation updated where needed +- [ ] Code follows best practices from `AGENTS.md` + +### Phase-Specific Checks + +#### Planning Discovery (problem_space, bsd) +- [ ] Problem space clearly defined +- [ ] Questions asked before documents created +- [ ] BSD has measurable success metrics + +#### Planning Requirements (user_stories, fsd) +- [ ] User stories have clear acceptance criteria +- [ ] FSD covers functional requirements + +#### Research +- [ ] Multiple technology options evaluated +- [ ] Trade-offs documented +- [ ] Recommendations have clear rationale + +#### Architecture +- [ ] Architecture is sound and scalable +- [ ] API specs are complete + +#### Implementation +- [ ] Implementation plan is broken into micro-PRs +- [ ] Each PR is independently testable +- [ ] Security considerations addressed + +#### Code (Backend/Frontend) +- [ ] Code compiles/builds successfully +- [ ] Tests included or planned +- [ ] Follows language-specific best practices +- [ ] No hardcoded secrets or credentials + +#### Review +- [ ] All review items addressed +- [ ] Security vulnerabilities fixed + +## Output Format + +``` +## QA Evaluation + +### Task: [what was requested] +### Subagent: [which agent ran] + +### Quality Gates +| Gate | Status | Notes | +|------|--------|-------| +| Gate 1 | PASS/FAIL | Details | + +### Issues Found +1. **Issue**: Description + - **Severity**: Critical/High/Medium/Low + - **Fix**: Suggested fix + +### Verdict +- **PASS**: Work meets quality standards +- **FAIL**: Work needs revision +- **CONDITIONAL**: Pass with minor issues noted +``` + +## Workflow + +1. Receive delegation from orchestrator with task details +2. Read the delivered work (documents, code, etc.) +3. Apply quality gates based on phase +4. Document any issues found +5. Return verdict to orchestrator + +## Important + +- Be thorough but fair - don't reject work for trivial issues +- Focus on critical problems that would block progress +- Provide actionable fix suggestions, not just criticism diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md index bb29f230..1e3221b6 100644 --- a/.opencode/agents/research.md +++ b/.opencode/agents/research.md @@ -1,52 +1,68 @@ --- -description: Unit research - technology evaluation and FSD +description: Research - technology evaluation and trade-offs mode: subagent --- -# Unit Research Agent +# Research Agent -Activate the **Trend Researcher** (from `agency-agents/product/product-trend-researcher.md`) +Evaluates technologies and documents trade-offs. + +## Reference Agent + +Activate **Trend Researcher** (from `agency-agents/product/product-trend-researcher.md`) Activate **Tool Evaluator** (from `agency-agents/testing/testing-tool-evaluator.md`) ## Your Task -Complete the research phase for the unit specified by the user. +Research technologies and create research documentation for a unit. ## Context -- Read `design/units/{UNIT_NAME}/` existing documents first +- Read `design/units/{UNIT_NAME}/fsd.md` first (functional requirements) +- Read `design/units/{UNIT_NAME}/user_stories.md` - Read `design/README.md` for ACE Framework patterns +- Unit directory: `design/units/{UNIT_NAME}/` -## Workflow - -### 1. Technology Research -Research and evaluate different approaches: -- Compare technology options -- Check active maintenance (GitHub activity, last release) -- Provide multiple alternatives, never just one -- Verify with web searches for current best practices +## Documents Created -### 2. Research Document -Create `research.md`: +### 1. Research (research.md) - Problem space summary -- Technology options evaluated -- Recommendations with rationale -- Trade-offs considered +- Technology options evaluated (NEVER recommend just one) +- Comparison matrix with trade-offs +- Recommendations with clear rationale +- Web search for current best practices -### 3. Functional Specification (FSD) -Create `fsd.md`: -- Functional requirements -- API contracts -- Data models -- Edge cases +### 2. Dependencies (dependencies.md) +- External dependencies +- Package manager requirements +- Version constraints +- Compatibility notes ## Templates -Use templates from `.agents/skills/unit-workflow/unit-templates/`: -- `research.md` -- `fsd.md` +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/research.md` +- `.agents/skills/unit-planning/unit-templates/dependencies.md` + +## Prerequisites + +- `fsd.md` must exist (functional requirements) +- `user_stories.md` must exist + +## Research Guidelines + +1. **Multiple Options**: Always provide at least 2-3 alternatives +2. **Active Maintenance**: Check GitHub activity, last release date +3. **Trade-offs**: Document pros/cons of each option +4. **Current Best Practices**: Verify with web searches ## Output -Create documents in `design/units/{UNIT_NAME}/` -Return file paths created and technology recommendations. +Create in `design/units/{UNIT_NAME}/`: +- `research.md` +- `dependencies.md` + +Return file paths and technology recommendations. diff --git a/.opencode/agents/review.md b/.opencode/agents/review.md index 571be6c1..21de69e3 100644 --- a/.opencode/agents/review.md +++ b/.opencode/agents/review.md @@ -1,52 +1,54 @@ --- -description: Unit review and testing +description: Unit review - code review and quality assurance mode: subagent --- -# Unit Review Agent +# Review Agent -For Code Review: Activate the **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) -For Testing: Activate the **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) +Performs code review and quality checks. + +## Reference Agent + +Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) +Activate **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) ## Your Task -Complete the review and testing phase for the unit specified by the user. +Review code implementation against design documents. ## Context -- Read all implementation documents in `design/units/{UNIT_NAME}/` +- Read `design/units/{UNIT_NAME}/fsd.md` first +- Read `design/units/{UNIT_NAME}/architecture.md` +- Read `design/units/{UNIT_NAME}/implementation.md` - Implementation is in `backend/` and/or `frontend/` ## Workflow -### 1. Testing Strategy -Create `testing.md`: -- Unit test requirements (80% coverage target) -- Integration test requirements -- E2E test requirements - -### 2. Code Review -- Review implementation against `fsd.md` and `architecture.md` -- Check for: - - Security vulnerabilities - - Error handling completeness - - Test coverage - - Code quality - -### 3. Evidence Collection +### 1. Code Review +Review implementation against specifications: +- Security vulnerabilities +- Error handling completeness +- Code quality +- Follows best practices from `AGENTS.md` + +### 2. Specification Compliance +Verify implementation matches: +- `fsd.md` functional requirements +- `architecture.md` design +- `api.md` contracts + +### 3. Test Coverage +- Verify unit tests exist +- Verify integration tests exist +- Check coverage meets 80% target + +### 4. Evidence Collection Activate **Evidence Collector** (from `agency-agents/testing/testing-evidence-collector.md`) to gather test evidence -### 4. Quality Gate -Activate **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) to verify quality gates - -## Templates - -Use templates from `.agents/skills/unit-workflow/unit-templates/`: -- `testing.md` - ## Output -- Updated `testing.md` with test cases - Review findings +- Security issues found - Quality gate status -- Any issues that need fixing +- Issues that need fixing diff --git a/.opencode/agents/tester.md b/.opencode/agents/tester.md index e08ab802..edbfd162 100644 --- a/.opencode/agents/tester.md +++ b/.opencode/agents/tester.md @@ -3,9 +3,14 @@ description: Runs tests for code changes using docker/make mode: subagent --- -# Unit Tester Agent +# Tester Agent -This agent runs tests for code changes in a safe manner. +Runs tests for code changes in a safe manner. + +## Reference Agent + +Activate **API Tester** (from `agency-agents/testing/testing-api-tester.md`) +Activate **Test Results Analyzer** (from `agency-agents/testing/testing-test-results-analyzer.md`) ## CRITICAL: Local Machine Restrictions @@ -16,35 +21,41 @@ This is running on the user's LOCAL machine. You MUST only use: **NEVER run arbitrary commands directly on the host.** -## Testing Commands +## Your Task + +Run tests and verify code works correctly. + +## Context + +- Tests are defined in `design/units/{UNIT_NAME}/testing.md` +- Implementation is in `backend/` and/or `frontend/` -### Start Services +## Workflow + +### 1. Start Services ```bash make up ``` -### Run Tests +### 2. Run Tests ```bash make test ``` -### Run API Tests Directly +### 3. Run API Tests Directly ```bash docker exec ace_api go test ./... ``` -### Test HTTP Endpoints +### 4. Test HTTP Endpoints ```bash curl -X GET http://localhost:8080/health ``` -## Workflow - -1. Start services with `make up` if not running -2. Run tests with `make test` -3. If tests fail, investigate with `docker exec` commands -4. Test specific endpoints with `curl` -5. Report results +### 5. Analyze Results +- If tests fail, investigate with `docker exec` commands +- Use `curl` to test specific endpoints +- Activate **Test Results Analyzer** if needed ## Output diff --git a/.opencode/agents/testing.md b/.opencode/agents/testing.md new file mode 100644 index 00000000..3496f99d --- /dev/null +++ b/.opencode/agents/testing.md @@ -0,0 +1,64 @@ +--- +description: Testing strategy and UI mockups +mode: subagent +--- + +# Testing Agent + +Handles testing strategy, UI mockups, and test planning. + +## Reference Agent + +Activate **Reality Checker** (from `agency-agents/testing/testing-reality-checker.md`) +Activate **Tool Evaluator** (from `agency-agents/testing/testing-tool-evaluator.md`) + +## Your Task + +Create testing strategy and UI mockup documents for a unit. + +## Context + +- Read `design/units/{UNIT_NAME}/implementation.md` first +- Read `design/units/{UNIT_NAME}/architecture.md` +- Read `design/units/{UNIT_NAME}/fsd.md` +- Read `design/README.md` for ACE Framework patterns +- Unit directory: `design/units/{UNIT_NAME}/` + +## Documents Created + +### 1. Testing (testing.md) +- Unit test requirements (80% coverage target) +- Integration test requirements +- E2E test requirements +- Test data strategy +- Performance testing requirements +- Security testing requirements + +### 2. Mockups (mockups.md) +- UI wireframes/descriptions +- Component hierarchy +- User flow visualizations +- Responsive breakpoints + +## Templates + +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/testing.md` +- `.agents/skills/unit-planning/unit-templates/mockups.md` + +## Prerequisites + +- `implementation.md` must exist +- `architecture.md` must exist +- `fsd.md` must exist + +## Output + +Create in `design/units/{UNIT_NAME}/`: +- `testing.md` +- `mockups.md` + +Return file paths and test strategy summary. diff --git a/AGENTS.md b/AGENTS.md index b2005ccc..18e3d39f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,49 +1,8 @@ -**CRITICAL** paths are non-negotiable steps, if you don't adhere to any of the **CRITICAL** steps, your work will be invalidated and thrown out. - -# Startup -- **CRITICAL**: On initialisation before responding to any messages from the user, run `make setup` to ensure agency-agents is available and distrobox is set up. This will clone the repo if not present. - # Design Documentation (Always Read First!) - **CRITICAL**: Always read `design/README.md` before starting any work - Reference `design/units/README.md` for individual unit documentation - Understanding the overall system design is essential before making any changes -# Unit Workflow -- **CRITICAL**: When working on units, ALWAYS use the Task tool to invoke `@orchestrator`. The orchestrator handles delegation to planning, research, implementation, review, and testing phases. -- Load `unit-planning` skill for template access when creating planning documents - -# OpenCode Agents - -| Agent | Purpose | -|-------|---------| -| `orchestrator` | Orchestrates the full unit workflow | -| `planning` | Problem space, BSD, user stories | -| `research` | Research, FSD | -| `implementation` | Architecture, implementation plan | -| `review` | Code review | -| `tester` | Runs tests via docker/make | - -# Project Structure -- `agency-agents` - Bespoke workflow instructions -- `design/` - All design documentation for the system - - `design/README.md` - Overall system architecture and design - - `design/units/` - Individual unit specifications (features, components, refactors) -- `devops` - Deployment files -- `documentation/` - Project documentation and changelogs - - `documentation/changelogs/` - Daily changelog files -- `backend/` - Go backend source code (when implemented) -- `frontend/` - SvelteKit/TypeScript frontend source code (when implemented) - -# Testing (Local Machine) -- **CRITICAL**: When testing on this local machine, ONLY use: - - `make` commands from Makefile - - `docker exec` commands to run tests inside containers - - `curl` to test HTTP endpoints -- **NEVER** run arbitrary commands directly on the host -- Use `make up` to start services, `make test` to run tests -- Use `docker exec` to run Go tests inside the api container -- Use `curl` to test API endpoints - # Documentation Updates **IMPORTANT**: Before making any changelog or documentation updates: diff --git a/Makefile b/Makefile index 94b523d8..1cd66ce8 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ dev: ## Full dev setup: clone agency-agents, setup distrobox, install deps echo "Distrobox created."; \ fi; \ echo "Installing dependencies..."; \ - distrobox enter --name $(DISTROBOX_NAME) -- /bin/sh -c "cd $$REPO_DIR && .dev/setup.sh" + distrobox enter --name $(DISTROBOX_NAME) -- /bin/sh -c "cd $$REPO_DIR && .dev/distrobox-setup.sh" @echo "" @# Step 3: Setup pre-commit hook @echo "$(BLUE)Setting up pre-commit hook...$(NC)" From cecb19dd66ca09f67af98c5b38ccfe2773a61870 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 11:29:10 +0200 Subject: [PATCH 04/32] feat: added opencode github integration --- .../memory/{long_term.json => long-term.json} | 1 + .../short-term/opencode-integration.json | 35 +-- .github/workflows/opencode.yml | 33 +++ .opencode/agents/orchestrator.md | 268 ++++++------------ .opencode/config.json | 5 + AGENTS.md | 20 +- 6 files changed, 161 insertions(+), 201 deletions(-) rename .agents/memory/{long_term.json => long-term.json} (88%) create mode 100644 .github/workflows/opencode.yml create mode 100644 .opencode/config.json diff --git a/.agents/memory/long_term.json b/.agents/memory/long-term.json similarity index 88% rename from .agents/memory/long_term.json rename to .agents/memory/long-term.json index 51617bb1..05193960 100644 --- a/.agents/memory/long_term.json +++ b/.agents/memory/long-term.json @@ -1,6 +1,7 @@ { "version": "1.0", "completed_units": {}, + "in_progress_units": [], "preferences": { "retry_count": 3, "auto_approve_github_issues": false diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index 63619f93..7159957a 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -1,20 +1,23 @@ { "unit": "opencode-integration", - "current_phase": "completed", - "status": "completed", - "completed_phases": [ - "planning-discovery", - "planning-requirements", - "research", - "architecture", - "implementation", - "testing", - "backend", - "frontend", - "review", - "tester" + "current_phase": "orchestrator", + "status": "in_progress", + "pending_tasks": [ + "Review orchestrator.md", + "Review planning-discovery.md", + "Review planning-requirements.md", + "Review research.md", + "Review architecture.md", + "Review implementation.md", + "Review testing.md", + "Review backend.md", + "Review frontend.md", + "Review review.md", + "Review tester.md", + "Review qa.md" ], - "pending_tasks": [], - "trigger_context": "user_request", - "last_updated": "2026-03-15T18:00:00Z" + "episodes": [ + { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" } + ], + "last_updated": "2026-03-15T20:35:00Z" } diff --git a/.github/workflows/opencode.yml b/.github/workflows/opencode.yml new file mode 100644 index 00000000..1062e38c --- /dev/null +++ b/.github/workflows/opencode.yml @@ -0,0 +1,33 @@ +name: opencode + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + +jobs: + opencode: + if: | + contains(github.event.comment.body, ' /oc') || + startsWith(github.event.comment.body, '/oc') || + contains(github.event.comment.body, ' /opencode') || + startsWith(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run opencode + uses: anomalyco/opencode/github@latest + env: + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + with: + model: opencode/minimax-m2.5-free \ No newline at end of file diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 1f57655e..491a2299 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -17,88 +17,61 @@ You are the central coordinator for the ACE Framework. **You never do work direc ## Memory System -You have access to memory stores in `.agents/memory/`: +You have access to memory stores in `.agents/memory/`. -### Short-term Memory - Per-Unit Files -Each unit has its own file: `.agents/memory/short-term/{unit-name}.json` +### Short-term Memory - Per-Unit -Example: `.agents/memory/short-term/observability.json` +**Location**: `.agents/memory/short-term/{unit-name}.json` -Structure: +**Purpose**: Tracks work-in-progress for a specific unit. Each unit has its own file. + +**When to load**: +- User says "work on X" → Load `short-term/x.json` +- GitHub event on branch `feature/x` → Load `short-term/x.json` +- New unit → Create `short-term/{new-unit}.json` + +**Structure**: ```json { "unit": "observability", "current_phase": "planning-discovery", "status": "in_progress", - "completed_phases": [], "pending_tasks": [], - "trigger_context": "user_request", + "episodes": [ + { + "phase": "planning-discovery", + "notes": [], + "timestamp": "2026-03-15T12:00:00Z" + } + ], "last_updated": "2026-03-15T12:00:00Z" } ``` -**How to find the right memory file:** -1. If user specifies unit → Load `.agents/memory/short-term/{unit}.json` -2. If GitHub event → Extract issue/PR number, find unit from branch name or context -3. If new session → Ask user which unit they're working on +**How to update**: +- Before delegation: Read the file to know current state +- After delegation: Write updated file with progress + +### Long-term Memory + +**Location**: `.agents/memory/long-term.json` -### Long-term Memory (`long_term.json`) - Persistent -Location: `.agents/memory/long_term.json` +**Purpose**: Persistent across all sessions. -Across all sessions: -- `completed_units`: Historical unit completion data +**Contains**: +- `completed_units`: Historical completion data - `preferences`: User preferences -- `agent_performance`: Which agents perform best for what tasks -- `learned_patterns`: Patterns learned from workflows +- `learned_patterns`: Patterns from workflows -### Memory Encoding Principles +### Memory Principles **Keep it Lean**: - Only store essential state - Delete completed tasks promptly -- Prune old events after phase completion - -**Episodic Memory**: -- Store significant events as episodes -- Format: `{ "episode": "start_unit_X", "unit": "X", "phase": "planning", "outcome": "success", "timestamp": "..." }` - -**Semantic Memory**: -- Store learned facts that persist -- Format: `{ "fact": "agent_Y_best_for_research", "confidence": 0.9, "evidence": "..." }` - -### Memory Operations - -**Before every delegation:** -1. Determine unit name from user request or trigger -2. Load `.agents/memory/short-term/{unit}.json` -3. Read long-term memory for preferences and patterns -4. Determine current phase and next steps - -**After every delegation:** -1. Update `.agents/memory/short-term/{unit}.json` with results -2. Extract any semantic learnings to long-term memory -3. Prune completed tasks -**Loading Unit Memory:** -- User says "work on observability" → Load `short-term/observability.json` -- GitHub event on branch `feature/observability` → Load `short-term/observability.json` -- New unit → Create `short-term/{new-unit}.json` +**Episodic Memory**: Captured in the `episodes` array in short-term memory. Each episode records what happened in a phase. -## Available Subagents - -| Subagent | Purpose | Documents Created | -|----------|---------|-------------------| -| `planning-discovery` | Problem space + BSD | `problem_space.md`, `bsd.md` | -| `planning-requirements` | User stories + FSD | `user_stories.md`, `fsd.md` | -| `research` | Tech evaluation + deps | `research.md`, `dependencies.md` | -| `architecture` | System design + API + monitoring | `architecture.md`, `api.md`, `monitoring.md` | -| `implementation` | Implementation plan + security + migrations | `implementation.md`, `security.md`, `migration_and_rollback.md` | -| `testing` | Testing strategy + mockups | `testing.md`, `mockups.md` | -| `backend` | Go backend code | Code in `backend/` | -| `frontend` | SvelteKit frontend code | Code in `frontend/` | -| `review` | Code review | Review findings | -| `tester` | Run tests via docker/make | Test results | -| `qa` | Quality assurance | QA verdict | +**Semantic Memory**: Stored in long-term memory's `learned_patterns` array. ## Workflow Phases @@ -116,110 +89,57 @@ The standard unit workflow sequence: ## Trigger Correlation -When a trigger comes in (GitHub comment, issue, etc.): -1. Parse the trigger (issue number, PR number, keywords) -2. Read short-term memory to find matching unit -3. If no match, check long-term memory for completed units -4. If still no match, ask user which unit this relates to -5. Set `trigger_context` in short-term memory +When a trigger comes in: + +1. **Parse the trigger**: + - User request: Extract unit name from request + - GitHub event: Extract from branch name or PR title + +2. **Find matching unit**: + - Check `.agents/memory/short-term/{unit}.json` + - If not found, check `.agents/memory/long-term.json` + - If still not found, ask user -### Trigger Types -- **GitHub Issue Comment**: Extract issue number → find unit -- **GitHub PR Comment**: Extract PR number → find unit from branch -- **GitHub Review Comment**: Map to unit being reviewed -- **User Request**: Parse unit name from request -- **New Session**: Resume from short-term memory active units +3. **Load memory**: Read the short-term memory file for that unit -## Error Handling & Retry Logic +4. **Resume**: Continue from the current phase in memory + +## Error Handling ### Retry Strategy - **Max retries**: 3 attempts per subagent task -- **Retry on**: Subagent failures, test failures, review failures +- **Retry on**: Subagent failures, test failures ### Escalation Flow -``` 1. First attempt: Delegate to subagent 2. If fails: Check error type - - Recoverable (timeout, transient): Retry up to 3x - - Non-recoverable (bad input, missing docs): Report to user + - Recoverable (timeout): Retry up to 3x + - Non-recoverable (bad input): Report to user 3. After 3 retries: Escalate to user with error details -4. User decides: Retry with new input, skip task, or abort -``` ## QA After Every Subagent -**CRITICAL**: After EVERY subagent completes, you MUST run the QA subagent to evaluate the work before proceeding. +**CRITICAL**: After EVERY subagent completes, you MUST run QA before proceeding. -### QA Check Process -1. Subagent completes work -2. Delegate to `@qa` subagent with: - - What the subagent was supposed to do +1. Delegate to `@qa` subagent with: + - What the subagent was supposed to deliver - What was actually delivered - Quality criteria to check -3. If QA passes → Continue to next phase -4. If QA fails → Request subagent to fix issues - -## GitHub Integration - -### Setup -- OpenCode GitHub App handles identity (appears as `opencode[bot]` on commits/PRs/comments) -- Install at: https://github.com/apps/opencode-agent -### CRITICAL: Always Reference the Unit +2. If QA passes → Continue to next phase -**Every PR and GitHub issue MUST include the unit name** so the orchestrator can load the correct memory file on new sessions. - -**In PR titles/descriptions:** -``` -[unit: opencode-integration] Add orchestrator memory system -``` - -**In commit messages:** -``` -feat: add memory system [unit: opencode-integration] -``` - -**In GitHub issues:** -``` -[unit: observability] How should we handle log aggregation? -``` - -This allows the orchestrator to: -1. Parse unit from PR/issue/branch -2. Load `.agents/memory/short-term/{unit}.json` -3. Resume work from where it left off - -### Workflow Triggers -- **PR comments**: `/opencode` or `/oc` triggers agent -- **Issue comments**: Can trigger agent -- **PR reviews**: Mention `@opencode` to trigger - -### Automatic Reactions -When you detect GitHub events (via user input or webhook): -1. Parse the unit from PR/issue/branch name -2. Load `.agents/memory/short-term/{unit}.json` -3. Correlate to current phase -4. Delegate to appropriate subagent -5. Post results back to GitHub - -## Telegram Integration (Placeholder) - -Future: Integrate with Telegram for real-time notifications and commands. -- User receives: Task completion, failures, approval requests -- User can send: Commands via Telegram bot +3. **If QA fails → ALWAYS fix the issues before proceeding** + - Request subagent to fix the specific issues + - Run QA again to verify fix + - Do NOT skip or ignore QA failures ## Creating New Agents -When you need to create a new specialized agent: - -### When to Create -- A new type of task emerges that doesn't fit existing agents -- A composite agent becomes too complex and needs splitting -- A pattern is identified that warrants its own agent +When you need a new specialized agent: -### How to Create -1. Create file in `.opencode/agents/` +1. Create `.opencode/agents/{name}.md` 2. Use this template: + ```markdown --- description: [One-line description] @@ -246,71 +166,59 @@ Activate [Agency Agent Name] (from `agency-agents/[path]/[file].md`) [What this agent produces] ``` -### Guidelines -- Always reference a pre-picked agency-agents md file -- Keep agents focused on a single responsibility -- Include clear prerequisites -- Document expected output - ## Usage Patterns ### Start New Unit ``` User: "Start the observability unit" -1. Check integrations are set up (long_term.json) -2. Read short-term memory for state -3. Read design/units/observability/ to see existing docs -4. If no docs → Launch @planning-discovery -5. Run @qa to evaluate output -6. Update memory with progress -7. Report to user +1. Create short-term/observability.json +2. Read design/units/observability/ to see existing docs +3. If no docs → Launch @planning-discovery +4. Run @qa to evaluate +5. Update memory +6. Report to user ``` ### Continue Existing Unit ``` User: "Continue the core-api unit" -1. Check integrations are set up -2. Read short-term memory for current phase -3. Read design/units/core-api/ for progress -4. Determine next phase needed -5. Launch appropriate subagent -6. Run @qa to evaluate output -7. Update memory -8. Report to user +1. Load short-term/core-api.json +2. Read design/units/core-api/ for progress +3. Determine next phase +4. Launch appropriate subagent +5. Run @qa +6. Update memory +7. Report to user ``` ### Handle GitHub Event ``` -User: "There's a comment on issue #42" -1. Check integrations are set up -2. Read issue content -3. Correlate to unit (short-term memory → long-term memory → ask user) -4. Set trigger_context -5. Determine task from comment -6. Delegate to appropriate subagent -7. Run @qa on results -8. Post results to GitHub -9. Update memory +User: "There's a comment on PR #42" +1. Extract unit from branch/PR +2. Load short-term/{unit}.json +3. Determine task from comment +4. Delegate to subagent +5. Run @qa +6. Post results to GitHub +7. Update memory ``` ### Handle Failure ``` Subagent fails after 3 retries -1. Collect error details and logs +1. Collect error details 2. Present to user with options: - Retry with different input - Skip this task - - Abort entire workflow + - Abort 3. Wait for user decision -4. Execute chosen path ``` ## Key Reminders -1. **Always check integrations first** - Don't proceed if not set up -2. **Always delegate** - Never do work directly -3. **Always QA** - Run @qa after every subagent -4. **Always update memory** - Track progress, correlate triggers +1. **Always delegate** - Never do work directly +2. **Always QA** - Run @qa after every subagent +3. **Always fix QA failures** - Never skip or ignore QA issues +4. **Always update memory** - Track progress in short-term file, track learnings in long-term 5. **Always retry** - Up to 3 times, then escalate -6. **Always confirm with user** - Before major actions like creating GitHub issues -7. **Keep memory lean** - Prune completed, store semantic learnings +6. **Keep memory lean** - Prune completed, store semantic learnings diff --git a/.opencode/config.json b/.opencode/config.json new file mode 100644 index 00000000..9fcf584a --- /dev/null +++ b/.opencode/config.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "orchestrator", + "model": "opencode/minimax-m2.5-free" +} diff --git a/AGENTS.md b/AGENTS.md index 18e3d39f..ca5e847f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,16 +1,16 @@ -# Design Documentation (Always Read First!) -- **CRITICAL**: Always read `design/README.md` before starting any work +# Design Documentation (CRITICAL) +- Always read `design/README.md` before starting any work or responding to any questions - Reference `design/units/README.md` for individual unit documentation - Understanding the overall system design is essential before making any changes -# Documentation Updates +# Documentation Updates (CRITICAL) -**IMPORTANT**: Before making any changelog or documentation updates: +Before making any changelog or documentation updates: 1. **Check the current date** - Use `date` command to get today's date 2. **Check existing changelog files** - List `documentation/changelogs/` to see what files exist and their dates 3. **Only update/add to existing files** - Never overwrite existing changelog content, only append new entries -**CRITICAL**: After every commit: +After every commit: 1. Update the relevant design documents in `design/units//` to reflect the final implementation 2. Update the `design/README.md` if relevant 3. Add entries to the daily changelog in `documentation/changelogs/.md` @@ -57,6 +57,16 @@ All code changes must include appropriate tests: ## GitHub Workflow +### Unit Reference (CRITICAL) +Every PR, commit, and issue MUST include the unit name so memory can be loaded on new sessions. + +**Format:** +- PR title: `[unit: opencode-integration] Add memory system` +- Commit: `feat: add memory system [unit: opencode-integration]` +- Issue: `[unit: observability] How should we handle logs?` + +This allows the orchestrator to resume work from the correct unit memory file. + ### Branch Naming - `feature/` - New features - `fix/` - Bug fixes From 9294fc67748104c1cbe6189203aa41da3d28dbfc Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:21:47 +0200 Subject: [PATCH 05/32] fix: add git staging for auto-fixed files in pre-commit hook - Pre-commit now stages changes after go fmt and eslint --fix - All integration tests pass with Go 1.26 - Updated distrobox-setup.sh for proper Go 1.26, docker-compose - go fmt applied to backend files [unit: opencode-integration] --- .dev/distrobox-setup.sh | 102 ++- .dev/pre-commit.sh | 293 +++--- .opencode/agents/orchestrator.md | 75 -- AGENTS.md | 68 ++ Makefile | 3 +- .../services/api/internal/config/config.go | 22 +- .../api/internal/handler/example_test.go | 2 +- .../api/internal/response/response.go | 6 +- .../api/internal/response/response_test.go | 6 +- .../api/internal/validator/validator_test.go | 2 +- backend/shared/messaging/client.go | 18 +- backend/shared/messaging/errors_test.go | 6 +- backend/shared/messaging/integration_test.go | 8 +- backend/shared/messaging/patterns.go | 14 +- backend/shared/messaging/stream.go | 42 +- backend/shared/messaging/stream_test.go | 12 +- backend/shared/messaging/subjects.go | 28 +- backend/shared/messaging/subjects_test.go | 14 +- backend/shared/shared.go | 2 +- backend/shared/telemetry/logger.go | 16 +- backend/shared/telemetry/logger_test.go | 54 +- backend/shared/telemetry/metrics.go | 40 +- backend/shared/telemetry/metrics_test.go | 54 +- backend/shared/telemetry/middleware_test.go | 38 +- backend/shared/telemetry/telemetry.go | 8 +- backend/shared/telemetry/telemetry_test.go | 28 +- backend/shared/telemetry/tracer_test.go | 36 +- backend/shared/telemetry/usage.go | 16 +- devops/dev/fe.Containerfile | 7 +- frontend/package-lock.json | 839 ++++++++++++++++++ frontend/package.json | 5 +- 31 files changed, 1386 insertions(+), 478 deletions(-) diff --git a/.dev/distrobox-setup.sh b/.dev/distrobox-setup.sh index 63529361..c4d84945 100755 --- a/.dev/distrobox-setup.sh +++ b/.dev/distrobox-setup.sh @@ -22,6 +22,10 @@ log_success() { echo -e "${GREEN}[OK]${NC} $1" } +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + # Check if we're in distrobox if [ ! -f /run/.toolboxenv ]; then echo "This script must be run inside the distrobox" @@ -32,33 +36,16 @@ fi # Ensure opencode PATH is available export PATH="$HOME/.opencode/bin:$PATH" -# Check if already set up (idempotency) -log_info "Checking existing installation..." -SKIP_SETUP=true - -for cmd in git make go node npm docker opencode; do - if ! command -v $cmd >/dev/null 2>&1; then - SKIP_SETUP=false - break - fi -done || true +# Ensure Go is in PATH +export PATH="/usr/local/go/bin:$HOME/.opencode/bin:$PATH" -if [ "$SKIP_SETUP" = true ]; then - log_success "All dependencies already installed!" - exit 0 -fi - -log_info "Installing development dependencies..." +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # Helper to run dnf with or without sudo run_dnf() { sudo dnf "$@" || dnf "$@" } -# Update package manager -log_info "Updating package manager..." -run_dnf update -y - # Install core tools log_info "Installing core tools..." run_dnf install -y \ @@ -66,35 +53,78 @@ run_dnf install -y \ make \ curl \ wget \ - golang \ nodejs \ npm \ python3 \ python3-pip \ - docker \ which \ findutils \ - jq + jq \ + docker \ + podman \ + docker-compose -# Install pipx (needed for distrobox) -log_info "Installing pipx..." -pip3 install --user pipx -pipx ensurepath +# Install/update system packages +log_info "Updating package manager..." +run_dnf update -y + +# Install Go 1.26+ (required by go.work) +log_info "Installing Go 1.26..." +GO_VERSION="1.26.0" +GO_INSTALL_DIR="/usr/local" +if [ ! -d "$GO_INSTALL_DIR/go" ] || ! "$GO_INSTALL_DIR/go/bin/go" version 2>/dev/null | grep -q "go1.2[6-9]"; then + curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tar.gz + sudo rm -rf $GO_INSTALL_DIR/go + sudo tar -C $GO_INSTALL_DIR -xzf /tmp/go.tar.gz + rm /tmp/go.tar.gz +fi +export PATH="/usr/local/go/bin:$PATH" +log_success "Go installed" -# Run go mod tidy for backend dependencies +# Install docker-compose (fedora uses docker-compose, not docker compose) +log_info "Installing docker-compose..." +if ! command -v docker-compose &> /dev/null; then + run_dnf install -y docker-compose +fi + +# Verify docker-compose works +if command -v docker-compose &> /dev/null; then + log_success "Docker compose ready" +else + log_error "Docker compose not available" +fi + +# Run go mod tidy for backend (always) log_info "Running go mod tidy..." -REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" if [ -d "$REPO_DIR/backend" ]; then cd "$REPO_DIR/backend" for module in $(go work edit -json 2>/dev/null | jq -r '.Use[] | .DiskPath' 2>/dev/null || echo ""); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then log_info "Tidying $module..." - (cd "$module" && go mod tidy 2>/dev/null || true) + (cd "$module" && go mod tidy) fi done fi -# Install OpenCode +# Install Go linting tools +log_info "Installing Go linting tools..." +go install golang.org/x/tools/cmd/goimports@latest +go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +# Install frontend deps (always) +log_info "Setting up frontend dependencies..." +if [ -d "$REPO_DIR/frontend" ]; then + cd "$REPO_DIR/frontend" + npm install + npx svelte-kit sync + + # Install additional linting tools + npm install -D eslint prettier eslint-config-prettier + + log_success "Frontend ready" +fi + +# Install OpenCode (if not exists) log_info "Installing OpenCode..." if ! command -v opencode &> /dev/null; then curl -fsSL https://opencode.ai/install | bash @@ -102,14 +132,4 @@ fi export PATH="$HOME/.opencode/bin:$PATH" echo "export PATH=\"\$HOME/.opencode/bin:\$PATH\"" >> ~/.bashrc 2>/dev/null || true -# Verify installations -log_info "Verifying tools..." -command -v git >/dev/null 2>&1 && log_success "git" -command -v make >/dev/null 2>&1 && log_success "make" -command -v go >/dev/null 2>&1 && log_success "go" -command -v node >/dev/null 2>&1 && log_success "node" -command -v npm >/dev/null 2>&1 && log_success "npm" -command -v docker >/dev/null 2>&1 && log_success "docker" -command -v opencode >/dev/null 2>&1 && log_success "opencode" - log_success "Development environment ready!" diff --git a/.dev/pre-commit.sh b/.dev/pre-commit.sh index a2ae47c4..e8024ec7 100755 --- a/.dev/pre-commit.sh +++ b/.dev/pre-commit.sh @@ -6,8 +6,12 @@ set +euo pipefail +# Add Go 1.26 to PATH if installed +if [ -d "/usr/local/go/bin" ]; then + export PATH="/usr/local/go/bin:$PATH" +fi + # Get the directory where this script is located -# Resolve symlinks to get the actual script location (handles git hook symlink case) SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || echo "${BASH_SOURCE[0]}")" SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" @@ -17,13 +21,7 @@ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Track if we're in a git repository -IS_GIT_REPO=false -if [ -d "$REPO_ROOT/.git" ]; then - IS_GIT_REPO=true -fi +NC='\033[0m' log_info() { echo -e "${BLUE}[PRE-COMMIT]${NC} $1" @@ -65,95 +63,56 @@ echo "" # ============================================ # 1. Go Build Verification # ============================================ -log_info "1/4: Go Build Verification..." +log_info "1/8: Go Build..." cd "$REPO_ROOT/backend" -# Check if go.work exists if [ ! -f "go.work" ]; then - log_skip "No Go workspace found, skipping build verification" + log_skip "No Go workspace found, skipping" ((SKIPPED++)) else - # Build all modules in the workspace individually - BUILD_SUCCESS=true - BUILD_WARNINGS=false for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then log_info "Building $module..." - BUILD_OUTPUT=$(cd "$module" && go build ./... 2>&1) - if [ $? -ne 0 ]; then - # Check if this is a pre-existing issue (not introduced by recent changes) - log_warn "Build issue in $module (may be pre-existing):" - echo "$BUILD_OUTPUT" | head -5 - BUILD_WARNINGS=true + if ! (cd "$module" && go build ./...) 2>&1; then + log_error "Build failed in $module" + FAILED=1 fi fi done - - if [ "$BUILD_WARNINGS" = true ]; then - log_warn "Build verification had warnings (pre-existing issues detected)" - fi - log_success "Go build verification complete" + [ $FAILED -eq 0 ] && log_success "Go build passed" fi echo "" # ============================================ -# 2. SQLC Generate Validation +# 2. Go Lint (auto-fix + check) # ============================================ -log_info "2/4: SQLC Generate Validation..." +log_info "2/8: Go Lint..." cd "$REPO_ROOT/backend" -# Track if any sqlc.yaml files exist -SQLC_EXISTS=false -SQLC_FAILED=false - -# Check each module in the workspace -for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do - if [ -d "$module" ] && [ -f "$module/sqlc.yaml" ]; then - SQLC_EXISTS=true - log_info "Running sqlc generate for $module..." - - # Save current generated files for comparison - if [ -d "$module/sqlc" ]; then - TEMP_DIR=$(mktemp -d) - cp -r "$module/sqlc" "$TEMP_DIR/sqlc_backup" +if [ ! -f "go.work" ]; then + log_skip "No Go workspace found, skipping" + ((SKIPPED++)) +else + for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + if [ -d "$module" ] && [ -f "$module/go.mod" ]; then + log_info "Formatting $module..." + (cd "$module" && go fmt ./...) 2>&1 || true - # Generate new files - if (cd "$module" && sqlc generate 2>&1); then - # Compare to see if anything changed - if diff -rq "$TEMP_DIR/sqlc_backup" "$module/sqlc" > /dev/null 2>&1; then - log_success "sqlc generate for $module - no changes needed" - else - log_warn "sqlc generate for $module - generated files are out of date" - log_info "Run 'sqlc generate' in $module to update generated files" - fi - - # Clean up - rm -rf "$TEMP_DIR" - else - log_warn "sqlc generate for $module had issues (may be pre-existing)" - fi - else - # No existing generated files, just run generate - if (cd "$module" && sqlc generate 2>&1); then - log_success "sqlc generate for $module - generated successfully" - else - log_warn "sqlc generate for $module had issues (may be pre-existing)" + log_info "Vetting $module..." + if ! (cd "$module" && go vet ./...) 2>&1; then + log_error "Go vet failed in $module" + FAILED=1 fi fi - fi -done - -if [ "$SQLC_EXISTS" = false ]; then - log_skip "No sqlc.yaml files found, skipping SQLC validation" - ((SKIPPED++)) -elif ! command -v sqlc &> /dev/null; then - log_skip "sqlc not installed, skipping SQLC validation" - ((SKIPPED++)) -else - log_success "SQLC validation complete" + done + +# Stage auto-fixed Go files (go fmt changes) +git -C "$REPO_ROOT" add . 2>/dev/null || true + + [ $FAILED -eq 0 ] && log_success "Go lint passed" fi echo "" @@ -161,73 +120,176 @@ echo "" # ============================================ # 3. Go Test Suite # ============================================ -log_info "3/4: Go Test Suite..." +log_info "3/8: Go Test..." cd "$REPO_ROOT/backend" -# Check if go.work exists if [ ! -f "go.work" ]; then - log_skip "No Go workspace found, skipping test suite" + log_skip "No Go workspace found, skipping" ((SKIPPED++)) else - # Test all modules in the workspace individually - TEST_SUCCESS=true for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then - if find "$module" -name "*_test.go" -type f 2>/dev/null | grep -q .; then - log_info "Testing $module..." - if ! (cd "$module" && go test -v ./...) 2>&1; then - log_warn "Tests failed or had issues in $module" - fi + log_info "Testing $module..." + # Run only unit tests (skip integration tests) + if ! (cd "$module" && go test -v -short ./...) 2>&1; then + log_error "Tests failed in $module" + FAILED=1 fi fi done - - log_success "Go test suite complete" + [ $FAILED -eq 0 ] && log_success "Go tests passed (unit only)" fi echo "" # ============================================ -# 4. Frontend Lint (svelte-check) +# 4. SQLC Generate Validation # ============================================ -log_info "4/4: Frontend Lint..." +log_info "4/8: SQLC Generate..." -cd "$REPO_ROOT/frontend" +cd "$REPO_ROOT/backend" + +SQLC_EXISTS=false -if [ -f "package.json" ]; then - # Check if svelte-kit is set up (need .svelte-kit directory) - if [ -d ".svelte-kit" ]; then - # Run svelte-check for TypeScript and Svelte validation - if npx svelte-check --threshold warning 2>&1; then - log_success "Frontend lint passed" +for module in $(go work edit -json 2>/dev/null | jq -r '.Use[] | .DiskPath' 2>/dev/null || echo ""); do + if [ -d "$module" ] && [ -f "$module/sqlc.yaml" ]; then + # Check if queries directory exists and has files + QUERY_DIR=$(cd "$module" && grep -A5 "queries:" sqlc.yaml 2>/dev/null | grep "path:" | head -1 | awk '{print $2}') + if [ -z "$QUERY_DIR" ] || [ ! -d "$module/$QUERY_DIR" ]; then + log_warn "No queries directory found in $module, skipping sqlc" + continue + fi + SQLC_EXISTS=true + log_info "Running sqlc generate for $module..." + if (cd "$module" && sqlc generate 2>&1); then + log_success "sqlc generate passed" else - log_warn "Frontend lint had warnings" + log_error "sqlc generate failed" + FAILED=1 fi - elif [ -d "node_modules" ]; then - log_info "SvelteKit not initialized, running svelte-kit sync..." - if npx svelte-kit sync 2>&1; then - log_success "SvelteKit sync complete" - if npx svelte-check --threshold warning 2>&1; then - log_success "Frontend lint passed" - else - log_warn "Frontend lint had warnings" - fi + fi +done + +[ "$SQLC_EXISTS" = false ] && log_skip "No sqlc.yaml found, skipping" + +echo "" + +# ============================================ +# 5. Frontend Lint (svelte-check + eslint) +# ============================================ +log_info "5/8: Frontend Lint..." + +cd "$REPO_ROOT/frontend" + +if [ ! -f "package.json" ]; then + log_skip "No frontend package.json found, skipping" + ((SKIPPED++)) +elif [ ! -d "node_modules" ] || [ ! -r "node_modules" ]; then + log_skip "Frontend node_modules not accessible (run make dev)" + ((SKIPPED++)) +else + # Run eslint --fix first + if [ -f ".eslintrc.cjs" ] || [ -f ".eslintrc.js" ] || [ -f "eslint.config.js" ]; then + log_info "Running eslint --fix..." + npx eslint --fix . 2>&1 || true + + # Stage auto-fixed files + git -C "$REPO_ROOT" add frontend/ 2>/dev/null || true + fi + + # Run svelte-check + if npx svelte-check 2>&1; then + log_success "Frontend lint passed" + else + log_error "Frontend lint failed" + FAILED=1 + fi +fi + +echo "" + +# ============================================ +# 6. Frontend Test +# ============================================ +log_info "6/8: Frontend Test..." + +cd "$REPO_ROOT/frontend" + +if [ ! -f "package.json" ]; then + log_skip "No frontend package.json found, skipping" + ((SKIPPED++)) +elif [ ! -d "node_modules" ]; then + log_skip "Frontend node_modules not accessible, skipping" + ((SKIPPED++)) +else + # Run tests if they exist + if [ -f "vitest.config.ts" ] || [ -f "vitest.config.js" ]; then + log_info "Running frontend tests..." + if npx vitest run 2>&1; then + log_success "Frontend tests passed" else - log_skip "SvelteKit setup incomplete, skipping frontend lint" - ((SKIPPED++)) + log_error "Frontend tests failed" + FAILED=1 fi else - log_skip "No node_modules found, skipping frontend lint" + log_skip "No frontend tests found, skipping" ((SKIPPED++)) fi +fi + +echo "" + +# ============================================ +# 7. Docker Compose Validation +# ============================================ +log_info "7/8: Docker Compose Validation..." + +COMPOSE_FAILED=false + +if command -v docker-compose &> /dev/null; then + for compose_file in devops/dev/compose.yml devops/prod/compose.yml; do + if [ -f "$REPO_ROOT/$compose_file" ]; then + log_info "Validating $compose_file..." + # Check if .env exists (required for prod) + COMPOSE_DIR=$(dirname "$REPO_ROOT/$compose_file") + if [ ! -f "$COMPOSE_DIR/.env" ] && [ "$compose_file" = "devops/prod/compose.yml" ]; then + log_warn "Prod compose - .env not found, skipping validation" + continue + fi + if ! docker-compose -f "$REPO_ROOT/$compose_file" config --quiet 2>&1; then + log_error "Compose file $compose_file is invalid" + FAILED=1 + fi + fi + done + [ $FAILED -eq 0 ] && log_success "Docker Compose validation passed" else - log_skip "No frontend package.json found, skipping lint" + log_skip "Docker compose not available, skipping" ((SKIPPED++)) fi echo "" +# ============================================ +# 8. Makefile Validation +# ============================================ +log_info "8/8: Makefile Validation..." + +if [ ! -f "$REPO_ROOT/Makefile" ]; then + log_skip "No Makefile found, skipping" + ((SKIPPED++)) +else + if make -n -f "$REPO_ROOT/Makefile" help >/dev/null 2>&1; then + log_success "Makefile validation passed" + else + log_error "Makefile has syntax errors" + FAILED=1 + fi +fi + +echo "" + # ============================================ # Summary # ============================================ @@ -236,29 +298,16 @@ echo " Pre-Commit Quality Gates Summary" echo "==========================================" echo "" -# Count warnings -WARNINGS=0 -if [ -n "${BUILD_WARNINGS:-}" ] && [ "$BUILD_WARNINGS" = true ]; then - ((WARNINGS++)) -fi - if [ $FAILED -gt 0 ]; then echo -e "${RED}$FAILED quality gate(s) FAILED${NC}" echo "" echo "Please fix the failing checks before committing." echo "" exit 1 -elif [ $WARNINGS -gt 0 ]; then - echo -e "${YELLOW}Quality gates completed with warnings${NC}" - echo "" - echo "Warnings indicate pre-existing issues or configuration problems." - echo "Review the output above for details." - echo "" - exit 0 elif [ $SKIPPED -gt 0 ]; then echo -e "${GREEN}All quality gates passed (or skipped)${NC}" echo "" - echo "Passed: $((4 - SKIPPED - FAILED))" + echo "Passed: $((8 - SKIPPED - FAILED))" echo "Skipped: $SKIPPED" echo "Failed: $FAILED" echo "" diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 491a2299..302d2232 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -15,64 +15,6 @@ You are the central coordinator for the ACE Framework. **You never do work direc 3. Run QA after each subagent completes 4. Report results back to the user -## Memory System - -You have access to memory stores in `.agents/memory/`. - -### Short-term Memory - Per-Unit - -**Location**: `.agents/memory/short-term/{unit-name}.json` - -**Purpose**: Tracks work-in-progress for a specific unit. Each unit has its own file. - -**When to load**: -- User says "work on X" → Load `short-term/x.json` -- GitHub event on branch `feature/x` → Load `short-term/x.json` -- New unit → Create `short-term/{new-unit}.json` - -**Structure**: -```json -{ - "unit": "observability", - "current_phase": "planning-discovery", - "status": "in_progress", - "pending_tasks": [], - "episodes": [ - { - "phase": "planning-discovery", - "notes": [], - "timestamp": "2026-03-15T12:00:00Z" - } - ], - "last_updated": "2026-03-15T12:00:00Z" -} -``` - -**How to update**: -- Before delegation: Read the file to know current state -- After delegation: Write updated file with progress - -### Long-term Memory - -**Location**: `.agents/memory/long-term.json` - -**Purpose**: Persistent across all sessions. - -**Contains**: -- `completed_units`: Historical completion data -- `preferences`: User preferences -- `learned_patterns`: Patterns from workflows - -### Memory Principles - -**Keep it Lean**: -- Only store essential state -- Delete completed tasks promptly - -**Episodic Memory**: Captured in the `episodes` array in short-term memory. Each episode records what happened in a phase. - -**Semantic Memory**: Stored in long-term memory's `learned_patterns` array. - ## Workflow Phases The standard unit workflow sequence: @@ -87,23 +29,6 @@ The standard unit workflow sequence: 9. **review** → Code review 10. **tester** → Run tests -## Trigger Correlation - -When a trigger comes in: - -1. **Parse the trigger**: - - User request: Extract unit name from request - - GitHub event: Extract from branch name or PR title - -2. **Find matching unit**: - - Check `.agents/memory/short-term/{unit}.json` - - If not found, check `.agents/memory/long-term.json` - - If still not found, ask user - -3. **Load memory**: Read the short-term memory file for that unit - -4. **Resume**: Continue from the current phase in memory - ## Error Handling ### Retry Strategy diff --git a/AGENTS.md b/AGENTS.md index ca5e847f..d364daf6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,6 +18,74 @@ After every commit: 5. Update API documentation if endpoints changed 6. Update the user wiki documentation/ folder with relevant changes +# Memory System + +You have access to memory stores in `.agents/memory/`. + +**Keep it Lean**: +- Only store essential state +- Delete completed tasks promptly + +**How to update**: +- Before delegation: Read the file to know current state +- After delegation: Write updated file with progress + +**Episodic Memory**: Captured in the `episodes` array in short-term memory. Each episode records what happened in a phase. + +**Semantic Memory**: Stored in long-term memory's `learned_patterns` array. + +## Long-term Memory + +**Location**: `.agents/memory/long-term.json` + +**Purpose**: Persistent across all sessions. + +**Contains**: +- `completed_units`: Historical completion data +- `preferences`: User preferences +- `learned_patterns`: Patterns from workflows + +## Short-term Memory - Per-Unit + +**Location**: `.agents/memory/short-term/{unit-name}.json` + +**Purpose**: Tracks work-in-progress for a specific unit. Each unit has its own file. + +**When to load**: Always try to find the relevant short term memory file for whatever unit you are working on. + +**Structure**: +```json +{ + "unit": "observability", + "current_phase": "planning-discovery", + "status": "in_progress", + "pending_tasks": [], + "episodes": [ + { + "phase": "planning-discovery", + "notes": [], + "timestamp": "2026-03-15T12:00:00Z" + } + ], + "last_updated": "2026-03-15T12:00:00Z" +} +``` + +### When a trigger comes in: + +1. **Parse the trigger**: + - User request: Extract unit name from request + - GitHub event: Extract from branch name or PR title/description or Issue title/description + +2. **Find matching unit**: + - Check `.agents/memory/short-term/{unit}.json` + - If not found, check `.agents/memory/long-term.json` + - If still not found, ask user + +3. **Load memory**: Read the short-term memory file for that unit + +4. **Resume**: Continue from the current phase in memory + # Working on the Code ## Coding Best Practices diff --git a/Makefile b/Makefile index 1cd66ce8..c9fa6269 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,8 @@ ifeq ($(filter $(ENVIRONMENT),$(VALID_ENVIRONMENTS)),) $(error ENVIRONMENT must be either 'dev' or 'prod', got: $(ENVIRONMENT)) endif -COMPOSE := $(ORCHESTRATOR) compose -f devops/$(ENVIRONMENT)/compose.yml +# Support both docker-compose and docker compose (fallback) +COMPOSE := $(shell command -v podman &>/dev/null && echo "podman compose" || (command -v docker-compose &>/dev/null && echo "docker-compose" || echo "docker compose")) -f devops/$(ENVIRONMENT)/compose.yml # Distrobox config DISTROBOX_NAME := opencode diff --git a/backend/services/api/internal/config/config.go b/backend/services/api/internal/config/config.go index afbb6577..ae02e035 100644 --- a/backend/services/api/internal/config/config.go +++ b/backend/services/api/internal/config/config.go @@ -31,7 +31,7 @@ type Config struct { NATSURL string // Telemetry configuration - Environment string + Environment string OTLPEndpoint string } @@ -90,16 +90,16 @@ func Load() (*Config, error) { } return &Config{ - DatabaseURL: dbURL, - APIHost: apiHost, - APIPort: apiPort, - CORSAllowedOrigins: origins, - LogLevel: logLevel, - JWTSecret: jwtSecret, - JWTExpirationHours: jwtExpirationHours, - NATSURL: natsURL, - Environment: environment, - OTLPEndpoint: otlpEndpoint, + DatabaseURL: dbURL, + APIHost: apiHost, + APIPort: apiPort, + CORSAllowedOrigins: origins, + LogLevel: logLevel, + JWTSecret: jwtSecret, + JWTExpirationHours: jwtExpirationHours, + NATSURL: natsURL, + Environment: environment, + OTLPEndpoint: otlpEndpoint, }, nil } diff --git a/backend/services/api/internal/handler/example_test.go b/backend/services/api/internal/handler/example_test.go index 9299683c..aa9f5039 100644 --- a/backend/services/api/internal/handler/example_test.go +++ b/backend/services/api/internal/handler/example_test.go @@ -68,7 +68,7 @@ func TestCreate_ValidationErrors(t *testing.T) { // Invalid request - missing name, invalid email body := map[string]string{ - "name": "", // required but empty + "name": "", // required but empty "email": "not-an-email", } bodyBytes, _ := json.Marshal(body) diff --git a/backend/services/api/internal/response/response.go b/backend/services/api/internal/response/response.go index 32e3eeab..d928a7aa 100644 --- a/backend/services/api/internal/response/response.go +++ b/backend/services/api/internal/response/response.go @@ -16,9 +16,9 @@ type APIResponse struct { // APIError represents an error response type APIError struct { - Code string `json:"code"` - Message string `json:"message"` - Details []FieldError `json:"details,omitempty"` + Code string `json:"code"` + Message string `json:"message"` + Details []FieldError `json:"details,omitempty"` } // FieldError represents a validation error for a specific field diff --git a/backend/services/api/internal/response/response_test.go b/backend/services/api/internal/response/response_test.go index 3557e2f7..6bc3d6fe 100644 --- a/backend/services/api/internal/response/response_test.go +++ b/backend/services/api/internal/response/response_test.go @@ -87,13 +87,13 @@ func TestValidationError(t *testing.T) { // Create a test struct with validation errors testStruct := TestStruct{ - Name: "A", // too short + Name: "A", // too short Email: "invalid", // not an email } - + validate := validator.New() err := validate.Struct(testStruct) - + ValidationError(w, err) if w.Code != http.StatusBadRequest { diff --git a/backend/services/api/internal/validator/validator_test.go b/backend/services/api/internal/validator/validator_test.go index 8a64fe6e..86015cc9 100644 --- a/backend/services/api/internal/validator/validator_test.go +++ b/backend/services/api/internal/validator/validator_test.go @@ -27,7 +27,7 @@ func TestValidateStruct_Valid(t *testing.T) { func TestValidateStruct_Invalid(t *testing.T) { testStruct := TestStruct{ - Name: "A", // too short (min=2) + Name: "A", // too short (min=2) Email: "invalid", // not an email } diff --git a/backend/shared/messaging/client.go b/backend/shared/messaging/client.go index 584a974f..c76faa4e 100644 --- a/backend/shared/messaging/client.go +++ b/backend/shared/messaging/client.go @@ -294,15 +294,15 @@ func (c *natsClient) Close() { // MockClient is a mock implementation of Client for testing. type MockClient struct { - mu sync.RWMutex - PublishedMsgs []*MockMsg - Subscriptions []*MockSubscription - StreamSubs []*MockStreamSubscription - RequestResp *nats.Msg - RequestErr error - HealthCheckErr error - DrainErr error - CloseCalled bool + mu sync.RWMutex + PublishedMsgs []*MockMsg + Subscriptions []*MockSubscription + StreamSubs []*MockStreamSubscription + RequestResp *nats.Msg + RequestErr error + HealthCheckErr error + DrainErr error + CloseCalled bool } // MockMsg represents a mock message. diff --git a/backend/shared/messaging/errors_test.go b/backend/shared/messaging/errors_test.go index 6a76d2a2..91de6523 100644 --- a/backend/shared/messaging/errors_test.go +++ b/backend/shared/messaging/errors_test.go @@ -7,9 +7,9 @@ import ( func TestErrorTypes(t *testing.T) { tests := []struct { - name string - err error - wantMsg string + name string + err error + wantMsg string }{ { name: "ErrConnectionFailed", diff --git a/backend/shared/messaging/integration_test.go b/backend/shared/messaging/integration_test.go index b6e99c71..515ed9ec 100644 --- a/backend/shared/messaging/integration_test.go +++ b/backend/shared/messaging/integration_test.go @@ -76,10 +76,10 @@ func getTestClient(t *testing.T) Client { t.Helper() client, err := NewClient(Config{ - URLs: srvURL, - Name: "test-client", - Timeout: 10 * time.Second, - MaxReconnect: 3, + URLs: srvURL, + Name: "test-client", + Timeout: 10 * time.Second, + MaxReconnect: 3, ReconnectWait: 1 * time.Second, }) require.NoError(t, err, "failed to create client") diff --git a/backend/shared/messaging/patterns.go b/backend/shared/messaging/patterns.go index e36e8516..a2bdc22d 100644 --- a/backend/shared/messaging/patterns.go +++ b/backend/shared/messaging/patterns.go @@ -174,13 +174,13 @@ func SubscribeToStreamWithEnvelopeAndSubject(ctx context.Context, client Client, // StreamSubscriptionConfig holds configuration for stream subscriptions. type StreamSubscriptionConfig struct { - Stream string - Consumer string - Subject string - Handler func(*nats.Msg) error - AutoAck bool - MaxAckWait time.Duration - MaxDeliver int + Stream string + Consumer string + Subject string + Handler func(*nats.Msg) error + AutoAck bool + MaxAckWait time.Duration + MaxDeliver int } // SubscribeToStreamWithConfig creates a JetStream subscription with detailed configuration. diff --git a/backend/shared/messaging/stream.go b/backend/shared/messaging/stream.go index e9fa4a61..a9d67da1 100644 --- a/backend/shared/messaging/stream.go +++ b/backend/shared/messaging/stream.go @@ -41,10 +41,10 @@ var StreamConfigs = []StreamConfig{ "ace.llm.response", }, Retention: nats.LimitsPolicy, - MaxBytes: 1 * 1024 * 1024 * 1024, // 1GB - MaxAge: 24 * time.Hour, - Storage: nats.FileStorage, - Replicas: 1, + MaxBytes: 1 * 1024 * 1024 * 1024, // 1GB + MaxAge: 24 * time.Hour, + Storage: nats.FileStorage, + Replicas: 1, }, { Name: "USAGE", @@ -53,10 +53,10 @@ var StreamConfigs = []StreamConfig{ "ace.usage.>", }, Retention: nats.LimitsPolicy, - MaxBytes: 100 * 1024 * 1024, // 100MB - MaxAge: 30 * 24 * time.Hour, // 30 days - Storage: nats.FileStorage, - Replicas: 1, + MaxBytes: 100 * 1024 * 1024, // 100MB + MaxAge: 30 * 24 * time.Hour, // 30 days + Storage: nats.FileStorage, + Replicas: 1, }, { Name: "SYSTEM", @@ -65,9 +65,9 @@ var StreamConfigs = []StreamConfig{ "ace.system.>", }, Retention: nats.WorkQueuePolicy, - MaxBytes: 10 * 1024 * 1024, // 10MB - Storage: nats.MemoryStorage, - Replicas: 1, + MaxBytes: 10 * 1024 * 1024, // 10MB + Storage: nats.MemoryStorage, + Replicas: 1, }, } @@ -126,16 +126,16 @@ type ConsumerConfig struct { // DefaultConsumerConfig returns default consumer configuration. func DefaultConsumerConfig(stream, consumer, filterSubject string) ConsumerConfig { return ConsumerConfig{ - Stream: stream, - Consumer: consumer, - Durable: consumer, - DeliverSubject: consumer, - FilterSubject: filterSubject, - DeliverPolicy: nats.DeliverNewPolicy, - AckPolicy: nats.AckExplicitPolicy, - AckWait: 30 * time.Second, - MaxDeliver: 3, - QueueGroup: "", + Stream: stream, + Consumer: consumer, + Durable: consumer, + DeliverSubject: consumer, + FilterSubject: filterSubject, + DeliverPolicy: nats.DeliverNewPolicy, + AckPolicy: nats.AckExplicitPolicy, + AckWait: 30 * time.Second, + MaxDeliver: 3, + QueueGroup: "", } } diff --git a/backend/shared/messaging/stream_test.go b/backend/shared/messaging/stream_test.go index b132051d..f617e660 100644 --- a/backend/shared/messaging/stream_test.go +++ b/backend/shared/messaging/stream_test.go @@ -11,17 +11,17 @@ import ( // MockJetStreamManager is a mock implementation of nats.JetStreamManager for testing. type MockJetStreamManager struct { - StreamConfigs map[string]*nats.StreamConfig + StreamConfigs map[string]*nats.StreamConfig ConsumerConfigs map[string]map[string]*nats.ConsumerConfig - AddStreamErr error - AddConsumerErr error - StreamInfoErr error + AddStreamErr error + AddConsumerErr error + StreamInfoErr error DeleteStreamErr error } func NewMockJetStreamManager() *MockJetStreamManager { return &MockJetStreamManager{ - StreamConfigs: make(map[string]*nats.StreamConfig), + StreamConfigs: make(map[string]*nats.StreamConfig), ConsumerConfigs: make(map[string]map[string]*nats.ConsumerConfig), } } @@ -286,7 +286,7 @@ func TestCreateConsumerWithDLQ(t *testing.T) { ConsumerName: "test-consumer", FilterSubject: "ace.engine.>", MaxDeliver: 3, - AckWait: 30 * time.Second, + AckWait: 30 * time.Second, } err = CreateConsumerWithDLQ(ctx, mock, dlqCfg) diff --git a/backend/shared/messaging/subjects.go b/backend/shared/messaging/subjects.go index ec7b7787..7963d951 100644 --- a/backend/shared/messaging/subjects.go +++ b/backend/shared/messaging/subjects.go @@ -9,12 +9,12 @@ import ( var ( prefixRegex = regexp.MustCompile(`^ace\.[a-z]+\.`) - enginePattern = regexp.MustCompile(`^ace\.engine\.[^.]+\.(layer|loop)\.[^.]+\.(input|output|status)$`) - memoryPattern = regexp.MustCompile(`^ace\.memory\.[^.]+\.(store|query|result)$`) - toolsPattern = regexp.MustCompile(`^ace\.tools\.[^.]+\.[^.]+\.(invoke|result)$`) - sensesPattern = regexp.MustCompile(`^ace\.senses\.[^.]+\.[^.]+\.event$`) - llmPattern = regexp.MustCompile(`^ace\.llm\.[^.]+\.(request|response)$`) - usagePattern = regexp.MustCompile(`^ace\.usage\.[^.]+\.(token|cost)$`) + enginePattern = regexp.MustCompile(`^ace\.engine\.[^.]+\.(layer|loop)\.[^.]+\.(input|output|status)$`) + memoryPattern = regexp.MustCompile(`^ace\.memory\.[^.]+\.(store|query|result)$`) + toolsPattern = regexp.MustCompile(`^ace\.tools\.[^.]+\.[^.]+\.(invoke|result)$`) + sensesPattern = regexp.MustCompile(`^ace\.senses\.[^.]+\.[^.]+\.event$`) + llmPattern = regexp.MustCompile(`^ace\.llm\.[^.]+\.(request|response)$`) + usagePattern = regexp.MustCompile(`^ace\.usage\.[^.]+\.(token|cost)$`) systemAgentsPattern = regexp.MustCompile(`^ace\.system\.agents\.(spawn|shutdown)$`) systemHealthPattern = regexp.MustCompile(`^ace\.system\.health\.[^.]+$`) ) @@ -26,7 +26,7 @@ type Subject string const ( SubjectEngineLayerInput Subject = "ace.engine.%s.layer.%s.input" SubjectEngineLayerOutput Subject = "ace.engine.%s.layer.%s.output" - SubjectEngineLoopStatus Subject = "ace.engine.%s.loop.%s.status" + SubjectEngineLoopStatus Subject = "ace.engine.%s.loop.%s.status" ) // Memory subjects @@ -61,9 +61,9 @@ const ( // System subjects const ( - SubjectSystemAgentsSpawn Subject = "ace.system.agents.spawn" + SubjectSystemAgentsSpawn Subject = "ace.system.agents.spawn" SubjectSystemAgentsShutdown Subject = "ace.system.agents.shutdown" - SubjectSystemHealth Subject = "ace.system.health.%s" + SubjectSystemHealth Subject = "ace.system.health.%s" ) // Format returns the subject with interpolated values. @@ -74,7 +74,7 @@ func (s Subject) Format(args ...interface{}) string { // Validate checks if the subject matches expected patterns. func (s Subject) Validate() error { subject := string(s) - + // Check for empty subject if subject == "" { return &MessagingError{ @@ -82,7 +82,7 @@ func (s Subject) Validate() error { Message: "subject cannot be empty", } } - + // Check if subject starts with "ace." prefix if !prefixRegex.MatchString(subject) { return &MessagingError{ @@ -90,7 +90,7 @@ func (s Subject) Validate() error { Message: "subject must start with 'ace..'", } } - + // Validate specific subject patterns using pre-compiled regex patterns := []struct { regex *regexp.Regexp @@ -105,13 +105,13 @@ func (s Subject) Validate() error { {systemAgentsPattern, "system agents subject invalid format"}, {systemHealthPattern, "system health subject invalid format"}, } - + for _, p := range patterns { if p.regex.MatchString(subject) { return nil } } - + return &MessagingError{ Code: "INVALID_SUBJECT", Message: fmt.Sprintf("subject '%s' does not match any known pattern", subject), diff --git a/backend/shared/messaging/subjects_test.go b/backend/shared/messaging/subjects_test.go index b4a2eb46..3c675348 100644 --- a/backend/shared/messaging/subjects_test.go +++ b/backend/shared/messaging/subjects_test.go @@ -112,32 +112,32 @@ func TestSubjectValidate(t *testing.T) { {"engine layer input", SubjectEngineLayerInput.Format("agent-1", "2"), false}, {"engine layer output", SubjectEngineLayerOutput.Format("agent-1", "3"), false}, {"engine loop status", SubjectEngineLoopStatus.Format("agent-1", "main"), false}, - + // Memory subjects {"memory store", SubjectMemoryStore.Format("agent-1"), false}, {"memory query", SubjectMemoryQuery.Format("agent-1"), false}, {"memory result", SubjectMemoryResult.Format("agent-1"), false}, - + // Tools subjects {"tools invoke", SubjectToolsInvoke.Format("agent-1", "browse"), false}, {"tools result", SubjectToolsResult.Format("agent-1", "browse"), false}, - + // Senses subjects {"senses event", SubjectSensesEvent.Format("agent-1", "chat"), false}, - + // LLM subjects {"llm request", SubjectLLMRequest.Format("agent-1"), false}, {"llm response", SubjectLLMResponse.Format("agent-1"), false}, - + // Usage subjects {"usage token", SubjectUsageToken.Format("agent-1"), false}, {"usage cost", SubjectUsageCost.Format("agent-1"), false}, - + // System subjects {"system agents spawn", string(SubjectSystemAgentsSpawn), false}, {"system agents shutdown", string(SubjectSystemAgentsShutdown), false}, {"system health", SubjectSystemHealth.Format("api"), false}, - + // Invalid subjects {"invalid", "invalid.subject", true}, {"ace invalid", "ace.invalid", true}, diff --git a/backend/shared/shared.go b/backend/shared/shared.go index bca6ce41..f77ae1ee 100644 --- a/backend/shared/shared.go +++ b/backend/shared/shared.go @@ -6,4 +6,4 @@ import "fmt" // Hello prints a greeting message. func Hello() { fmt.Println("Hello from shared package!") -} \ No newline at end of file +} diff --git a/backend/shared/telemetry/logger.go b/backend/shared/telemetry/logger.go index 27940313..26332aa6 100644 --- a/backend/shared/telemetry/logger.go +++ b/backend/shared/telemetry/logger.go @@ -7,11 +7,11 @@ import ( // LogFields holds optional logging fields for correlation type LogFields struct { - TraceID string - SpanID string - AgentID string - CycleID string - SessionID string + TraceID string + SpanID string + AgentID string + CycleID string + SessionID string CorrelationID string } @@ -64,9 +64,9 @@ func NewLogger(serviceName, environment string) (*zap.Logger, error) { // Build logger with JSON encoder config := zap.Config{ Level: zap.NewAtomicLevelAt(level), - Encoding: "json", - EncoderConfig: encoderConfig, - OutputPaths: []string{"stdout"}, + Encoding: "json", + EncoderConfig: encoderConfig, + OutputPaths: []string{"stdout"}, ErrorOutputPaths: []string{"stderr"}, } diff --git a/backend/shared/telemetry/logger_test.go b/backend/shared/telemetry/logger_test.go index 122227f1..ecf77572 100644 --- a/backend/shared/telemetry/logger_test.go +++ b/backend/shared/telemetry/logger_test.go @@ -28,12 +28,12 @@ func TestNewLoggerProduction(t *testing.T) { func TestNewLoggerJSONOutput(t *testing.T) { // Create a buffer to capture output buf, testLogger := createTestLogger() - + testLogger.Info("test message") testLogger.Sync() output := buf.String() - + // Parse JSON var logEntry map[string]interface{} err := json.Unmarshal([]byte(output), &logEntry) @@ -56,18 +56,18 @@ func TestNewLoggerDebugLevel(t *testing.T) { buf, testLogger := createTestLoggerWithLevel(zapcore.DebugLevel) testLogger.Debug("debug test") testLogger.Sync() - + output := buf.String() assert.Contains(t, output, "debug test") } func TestNewLoggerWithFields(t *testing.T) { fields := LogFields{ - TraceID: "trace-123", - SpanID: "span-456", - AgentID: "agent-789", - CycleID: "cycle-001", - SessionID: "session-002", + TraceID: "trace-123", + SpanID: "span-456", + AgentID: "agent-789", + CycleID: "cycle-001", + SessionID: "session-002", CorrelationID: "corr-003", } @@ -93,14 +93,14 @@ func TestNewLoggerWithFields(t *testing.T) { encoder := zapcore.NewJSONEncoder(encoderConfig) core := zapcore.NewCore(encoder, zapcore.AddSync(buf), zapcore.InfoLevel) testLogger := zap.New(core) - + // Add fields to the test logger (simulating what NewLoggerWithFields does) testLogger = fields.AddFields(testLogger) testLogger = testLogger.With(zap.String("service_name", "test-service")) - + testLogger.Info("test with fields") testLogger.Sync() - + output := buf.String() var logEntry map[string]interface{} err = json.Unmarshal([]byte(output), &logEntry) @@ -117,7 +117,7 @@ func TestNewLoggerWithFields(t *testing.T) { func TestNewLoggerPartialFields(t *testing.T) { fields := LogFields{ - AgentID: "agent-789", + AgentID: "agent-789", CycleID: "cycle-001", } @@ -143,14 +143,14 @@ func TestNewLoggerPartialFields(t *testing.T) { encoder := zapcore.NewJSONEncoder(encoderConfig) core := zapcore.NewCore(encoder, zapcore.AddSync(buf), zapcore.InfoLevel) testLogger := zap.New(core) - + // Add fields to the test logger (simulating what NewLoggerWithFields does) testLogger = fields.AddFields(testLogger) testLogger = testLogger.With(zap.String("service_name", "test-service")) - + testLogger.Info("test with partial fields") testLogger.Sync() - + output := buf.String() var logEntry map[string]interface{} err = json.Unmarshal([]byte(output), &logEntry) @@ -159,7 +159,7 @@ func TestNewLoggerPartialFields(t *testing.T) { // Verify only set fields assert.Equal(t, "agent-789", logEntry["agent_id"]) assert.Equal(t, "cycle-001", logEntry["cycle_id"]) - + // Verify unset fields are not present assert.NotContains(t, logEntry, "trace_id") assert.NotContains(t, logEntry, "span_id") @@ -172,9 +172,9 @@ func TestLogFieldsAddFields(t *testing.T) { require.NoError(t, err) fields := LogFields{ - TraceID: "trace-123", - AgentID: "agent-456", - CycleID: "cycle-789", + TraceID: "trace-123", + AgentID: "agent-456", + CycleID: "cycle-789", } loggerWithFields := fields.AddFields(logger) @@ -192,7 +192,7 @@ func TestNewLoggerWarnLevel(t *testing.T) { buf, testLogger := createTestLoggerWithLevel(zapcore.WarnLevel) testLogger.Warn("warning message") testLogger.Sync() - + output := buf.String() var logEntry map[string]interface{} err := json.Unmarshal([]byte(output), &logEntry) @@ -205,7 +205,7 @@ func TestNewLoggerErrorLevel(t *testing.T) { buf, testLogger := createTestLoggerWithLevel(zapcore.ErrorLevel) testLogger.Error("error message") testLogger.Sync() - + output := buf.String() var logEntry map[string]interface{} err := json.Unmarshal([]byte(output), &logEntry) @@ -218,12 +218,12 @@ func TestNewLoggerTimestamp(t *testing.T) { buf, testLogger := createTestLogger() testLogger.Info("timestamp test") testLogger.Sync() - + output := buf.String() var logEntry map[string]interface{} err := json.Unmarshal([]byte(output), &logEntry) require.NoError(t, err) - + // Verify timestamp exists and is in ISO8601 format assert.Contains(t, logEntry, "timestamp") timestamp, ok := logEntry["timestamp"].(string) @@ -239,7 +239,7 @@ func createTestLogger() (*bytes.Buffer, *zap.Logger) { // createTestLoggerWithLevel creates a test logger with a specific level that writes to a buffer func createTestLoggerWithLevel(level zapcore.Level) (*bytes.Buffer, *zap.Logger) { buf := &bytes.Buffer{} - + // Create encoder config matching NewLogger encoderConfig := zapcore.EncoderConfig{ TimeKey: "timestamp", @@ -254,13 +254,13 @@ func createTestLoggerWithLevel(level zapcore.Level) (*bytes.Buffer, *zap.Logger) EncodeDuration: zapcore.SecondsDurationEncoder, EncodeName: zapcore.FullNameEncoder, } - + encoder := zapcore.NewJSONEncoder(encoderConfig) core := zapcore.NewCore(encoder, zapcore.AddSync(buf), level) - + logger := zap.New(core) logger = logger.With(zap.String("service_name", "test-service")) - + return buf, logger } diff --git a/backend/shared/telemetry/metrics.go b/backend/shared/telemetry/metrics.go index fbb08df3..1efb92d7 100644 --- a/backend/shared/telemetry/metrics.go +++ b/backend/shared/telemetry/metrics.go @@ -17,8 +17,8 @@ import ( const ( MetricHTTPRequestDuration = "http_request_duration_seconds" MetricHTTPRequestsTotal = "http_requests_total" - MetricHTTPActiveRequests = "http_active_requests" - + MetricHTTPActiveRequests = "http_active_requests" + // NATS metrics MetricNATSMessagesPublished = "nats_messages_published_total" MetricNATSMessagesConsumed = "nats_messages_consumed_total" @@ -26,12 +26,12 @@ const ( // Label names (low cardinality only) const ( - LabelServiceName = "service_name" - LabelMethod = "method" - LabelPath = "path" - LabelStatusCode = "status_code" - LabelNATSService = "nats_service" // Service name for NATS metrics - LabelNATSSubject = "nats_subject" // Subject pattern (e.g., "ace.usage.event") + LabelServiceName = "service_name" + LabelMethod = "method" + LabelPath = "path" + LabelStatusCode = "status_code" + LabelNATSService = "nats_service" // Service name for NATS metrics + LabelNATSSubject = "nats_subject" // Subject pattern (e.g., "ace.usage.event") ) // UUID regex pattern (matches standard UUID format) @@ -51,13 +51,13 @@ var ( // Metrics holds all standard metrics type Metrics struct { - requestDuration *prometheus.HistogramVec - requestsTotal *prometheus.CounterVec - activeRequests *prometheus.GaugeVec + requestDuration *prometheus.HistogramVec + requestsTotal *prometheus.CounterVec + activeRequests *prometheus.GaugeVec natsMessagesPublished *prometheus.CounterVec natsMessagesConsumed *prometheus.CounterVec - registry *prometheus.Registry - meter metric.Meter // OTel meter for potential future use + registry *prometheus.Registry + meter metric.Meter // OTel meter for potential future use } // getGlobalMetrics returns the singleton metrics instance @@ -79,7 +79,7 @@ func newMetrics(reg *prometheus.Registry) *Metrics { if reg == nil { reg = prometheus.NewRegistry() } - + metrics := &Metrics{ requestDuration: prometheus.NewHistogramVec( prometheus.HistogramOpts{ @@ -118,16 +118,16 @@ func newMetrics(reg *prometheus.Registry) *Metrics { []string{LabelNATSService, LabelNATSSubject}, ), registry: reg, - meter: nil, + meter: nil, } - + // Register metrics with the registry reg.MustRegister(metrics.requestDuration) reg.MustRegister(metrics.requestsTotal) reg.MustRegister(metrics.activeRequests) reg.MustRegister(metrics.natsMessagesPublished) reg.MustRegister(metrics.natsMessagesConsumed) - + return metrics } @@ -173,8 +173,8 @@ func MetricsMiddleware(serviceName string) func(http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Skip metrics and health endpoints to avoid recursion // Health check paths: /health, /health/live, /health/ready - if r.URL.Path == "/metrics" || r.URL.Path == "/health" || - r.URL.Path == "/health/live" || r.URL.Path == "/health/ready" { + if r.URL.Path == "/metrics" || r.URL.Path == "/health" || + r.URL.Path == "/health/live" || r.URL.Path == "/health/ready" { next.ServeHTTP(w, r) return } @@ -295,7 +295,7 @@ type metricsRecorder struct { func NewMetricsRecorder(serviceName string) MetricsRecorder { return &metricsRecorder{ serviceName: serviceName, - metrics: getGlobalMetrics(), + metrics: getGlobalMetrics(), } } diff --git a/backend/shared/telemetry/metrics_test.go b/backend/shared/telemetry/metrics_test.go index 7f717d5f..010a6547 100644 --- a/backend/shared/telemetry/metrics_test.go +++ b/backend/shared/telemetry/metrics_test.go @@ -231,13 +231,13 @@ func TestIsAlphanumericID(t *testing.T) { {"abc123def456", true}, {"ABC123DEF456", true}, {"550e8400e29b41d4a716446655440000", true}, - {"12345678", true}, // 8 chars - all digits - {"123abcde", true}, // 8 chars - mixed - {"abc12345", true}, // 8 chars - mixed + {"12345678", true}, // 8 chars - all digits + {"123abcde", true}, // 8 chars - mixed + {"abc12345", true}, // 8 chars - mixed {"", false}, - {"abc123", false}, // too short (6 chars) - {"abcdefgh", false}, // too short, no digits - {"abc-123", false}, // contains hyphen + {"abc123", false}, // too short (6 chars) + {"abcdefgh", false}, // too short, no digits + {"abc-123", false}, // contains hyphen } for _, tt := range tests { @@ -255,12 +255,12 @@ func TestGetPathLabelTruncatesLongPath(t *testing.T) { func TestRegisterMetrics(t *testing.T) { handler := RegisterMetrics() assert.NotNil(t, handler) - + // Verify it's a valid http.Handler rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/metrics", nil) handler.ServeHTTP(rec, req) - + // Should return 200 with Prometheus content assert.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Header().Get("Content-Type"), "text/plain") @@ -268,13 +268,13 @@ func TestRegisterMetrics(t *testing.T) { func TestMetricsRecorderInterface(t *testing.T) { rec := NewMetricsRecorder("test-service") - + // Test that it implements the interface var _ MetricsRecorder = rec - + // Test recording rec.RecordRequest("GET", "/api/test", 200, 100*1000*1000) // 100ms in nanoseconds - + // Record some more requests rec.RecordRequest("POST", "/api/users", 201, 50*1000*1000) rec.RecordRequest("GET", "/api/users", 500, 200*1000*1000) @@ -282,7 +282,7 @@ func TestMetricsRecorderInterface(t *testing.T) { func TestMetricsRecorderIncrementDecrement(t *testing.T) { rec := NewMetricsRecorder("test-service") - + rec.IncrementActiveRequests() rec.IncrementActiveRequests() rec.DecrementActiveRequests() @@ -304,20 +304,20 @@ func TestLabelConstants(t *testing.T) { func TestMetricsMiddlewareWithVariousMethods(t *testing.T) { methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH"} - + for _, method := range methods { t.Run(method, func(t *testing.T) { testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) - + middleware := MetricsMiddleware("test-service") handler := middleware(testHandler) - + req := httptest.NewRequest(method, "/test", nil) w := httptest.NewRecorder() handler.ServeHTTP(w, req) - + assert.Equal(t, http.StatusOK, w.Code) }) } @@ -346,12 +346,12 @@ func TestMetricsPrometheusFormat(t *testing.T) { // Verify Prometheus format body := rec.Body.String() - + // Check for metric names assert.Contains(t, body, "http_request_duration_seconds") assert.Contains(t, body, "http_requests_total") assert.Contains(t, body, "http_active_requests") - + // Check for labels assert.Contains(t, body, "service_name") assert.Contains(t, body, "method") @@ -362,15 +362,15 @@ func TestMetricsPrometheusFormat(t *testing.T) { func TestNoHighCardinalityLabels(t *testing.T) { // Create and register new metrics to test cardinality rec := NewMetricsRecorder("cardinality-test") - + // Record many different paths for i := 0; i < 100; i++ { rec.RecordRequest("GET", "/api/item/"+strconv.Itoa(i), 200, 10000000) } - + // Record with different users (should NOT be a label) // This is just to verify the design - agentId should NOT be in labels - + // The metrics should only have low-cardinality labels // This test passes if the code compiles and runs without agentId } @@ -393,7 +393,7 @@ func TestMetricsMiddlewareConcurrent(t *testing.T) { done <- true }() } - + // Wait for all to complete for i := 0; i < 10; i++ { <-done @@ -402,23 +402,23 @@ func TestMetricsMiddlewareConcurrent(t *testing.T) { func TestMetricsEndToEnd(t *testing.T) { require := require.New(t) - + // Create recorder rec := NewMetricsRecorder("e2e-test") - + // Simulate request lifecycle rec.IncrementActiveRequests() rec.RecordRequest("GET", "/api/users", 200, 50*1000*1000) rec.DecrementActiveRequests() - + // Get metrics metricsHandler := RegisterMetrics() rec2 := httptest.NewRecorder() req := httptest.NewRequest("GET", "/metrics", nil) metricsHandler.ServeHTTP(rec2, req) - + require.Equal(http.StatusOK, rec2.Code) - + // Verify content body := rec2.Body.String() require.Contains(body, "http_request_duration_seconds") diff --git a/backend/shared/telemetry/middleware_test.go b/backend/shared/telemetry/middleware_test.go index a2ce29bb..8acd61e9 100644 --- a/backend/shared/telemetry/middleware_test.go +++ b/backend/shared/telemetry/middleware_test.go @@ -177,7 +177,7 @@ func TestLoggerMiddlewareCapturesStatusCode(t *testing.T) { req := httptest.NewRequest("POST", "/api/users", nil) w := httptest.NewRecorder() - + // Wrap to capture status wrapped := &responseWriter{ResponseWriter: w, statusCode: 0} handler.ServeHTTP(wrapped, req) @@ -204,35 +204,35 @@ func TestLoggerMiddlewareWithTraceContext(t *testing.T) { func TestGetClientIP(t *testing.T) { tests := []struct { - name string - remoteAddr string + name string + remoteAddr string xForwardedFor string - xRealIP string - expectedIP string + xRealIP string + expectedIP string }{ { - name: "remote addr only", - remoteAddr: "192.168.1.1:12345", - expectedIP: "192.168.1.1", + name: "remote addr only", + remoteAddr: "192.168.1.1:12345", + expectedIP: "192.168.1.1", }, { - name: "x-forwarded-for", - remoteAddr: "10.0.0.1:12345", + name: "x-forwarded-for", + remoteAddr: "10.0.0.1:12345", xForwardedFor: "203.0.113.1, 70.41.3.18", - expectedIP: "203.0.113.1", + expectedIP: "203.0.113.1", }, { - name: "x-real-ip", - remoteAddr: "10.0.0.1:12345", - xRealIP: "198.51.100.1", - expectedIP: "198.51.100.1", + name: "x-real-ip", + remoteAddr: "10.0.0.1:12345", + xRealIP: "198.51.100.1", + expectedIP: "198.51.100.1", }, { - name: "x-forwarded-for takes precedence over x-real-ip", - remoteAddr: "10.0.0.1:12345", + name: "x-forwarded-for takes precedence over x-real-ip", + remoteAddr: "10.0.0.1:12345", xForwardedFor: "203.0.113.1", - xRealIP: "198.51.100.1", - expectedIP: "203.0.113.1", + xRealIP: "198.51.100.1", + expectedIP: "203.0.113.1", }, } diff --git a/backend/shared/telemetry/telemetry.go b/backend/shared/telemetry/telemetry.go index 987eb9a9..33833bcf 100644 --- a/backend/shared/telemetry/telemetry.go +++ b/backend/shared/telemetry/telemetry.go @@ -9,19 +9,19 @@ import ( "go.opentelemetry.io/otel/exporters/prometheus" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/trace" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + "go.opentelemetry.io/otel/trace" "go.uber.org/zap" ) // Config holds the telemetry configuration type Config struct { - ServiceName string // Service name (e.g., "api", "agent") - Environment string // Environment: "dev" or "prod" - OTLPEndpoint string // OTel Collector endpoint for traces/metrics + ServiceName string // Service name (e.g., "api", "agent") + Environment string // Environment: "dev" or "prod" + OTLPEndpoint string // OTel Collector endpoint for traces/metrics } // LoadConfig loads telemetry configuration from environment variables diff --git a/backend/shared/telemetry/telemetry_test.go b/backend/shared/telemetry/telemetry_test.go index 64732574..1d56dee8 100644 --- a/backend/shared/telemetry/telemetry_test.go +++ b/backend/shared/telemetry/telemetry_test.go @@ -23,16 +23,16 @@ func TestConfig(t *testing.T) { func TestUsageEventJSON(t *testing.T) { _ = UsageEvent{ - AgentID: "agent-123", - CycleID: "cycle-456", - SessionID: "session-789", - ServiceName: "api", - OperationType: OperationTypeLLMCall, - ResourceType: ResourceTypeAPI, - CostUSD: 0.05, - DurationMs: 1500, - TokenCount: 1000, - Metadata: map[string]string{"model": "gpt-4"}, + AgentID: "agent-123", + CycleID: "cycle-456", + SessionID: "session-789", + ServiceName: "api", + OperationType: OperationTypeLLMCall, + ResourceType: ResourceTypeAPI, + CostUSD: 0.05, + DurationMs: 1500, + TokenCount: 1000, + Metadata: map[string]string{"model": "gpt-4"}, } // Verify operation type constant @@ -104,7 +104,7 @@ func TestInit(t *testing.T) { require.NotNil(t, telemetry) require.NotNil(t, telemetry.Logger) require.NotNil(t, telemetry.Shutdown) - + // Test shutdown err := telemetry.Shutdown(ctx) assert.NoError(t, err) @@ -131,7 +131,7 @@ func TestSpanAttributesJSON(t *testing.T) { jsonBytes, err := attrs.MarshalJSON() require.NoError(t, err) - + // Verify JSON contains expected keys assert.Contains(t, string(jsonBytes), "agent_id") assert.Contains(t, string(jsonBytes), "cycle_id") @@ -196,10 +196,10 @@ func TestNATSCarrier_WithHeader(t *testing.T) { Header: nats.Header{"traceparent": []string{"00-abc-123"}}, } carrier := NATSCarrier{msg: msg} - + assert.Equal(t, "00-abc-123", carrier.Get("traceparent")) assert.Contains(t, carrier.Keys(), "traceparent") - + carrier.Set("tracestate", "vendor=custom") assert.Equal(t, "vendor=custom", carrier.Get("tracestate")) } diff --git a/backend/shared/telemetry/tracer_test.go b/backend/shared/telemetry/tracer_test.go index 68bcb9e0..b34b8a13 100644 --- a/backend/shared/telemetry/tracer_test.go +++ b/backend/shared/telemetry/tracer_test.go @@ -17,7 +17,7 @@ func TestHealthCheckNotInitialized(t *testing.T) { // Either the provider is not initialized OR the exporter connection is down // Both are acceptable for this test if err != nil { - assert.True(t, err == ErrTracerNotInitialized || err == ErrExporterConnectionDown || + assert.True(t, err == ErrTracerNotInitialized || err == ErrExporterConnectionDown || errors.Is(err, ErrExporterConnectionDown)) } } @@ -32,7 +32,7 @@ func TestHealthCheckExporterDown(t *testing.T) { ctx := context.Background() telemetry, err := Init(ctx, config) - + // If initialization succeeds, test the health check if err == nil && telemetry != nil { // Health check might fail because the endpoint doesn't exist @@ -43,16 +43,16 @@ func TestHealthCheckExporterDown(t *testing.T) { func TestExtractHTTP(t *testing.T) { // Test extracting trace context from HTTP headers ctx := context.Background() - + // Create headers with W3C trace context headers := http.Header{} headers.Set("traceparent", "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01") headers.Set("tracestate", "vendor=custom") headers.Set("baggage", "key1=value1") - + // Extract trace context newCtx := ExtractHTTP(ctx, headers) - + // The context should be updated (we can't easily verify without a span) assert.NotNil(t, newCtx) } @@ -61,7 +61,7 @@ func TestExtractHTTPWithEmptyHeaders(t *testing.T) { // Test extracting with empty headers ctx := context.Background() headers := http.Header{} - + newCtx := ExtractHTTP(ctx, headers) assert.NotNil(t, newCtx) } @@ -73,7 +73,7 @@ func TestExtractHTTPWithHeaders(t *testing.T) { "traceparent": {"00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01"}, "tracestate": {"vendor=custom"}, } - + newCtx := ExtractHTTPWithHeaders(ctx, headers) assert.NotNil(t, newCtx) } @@ -82,7 +82,7 @@ func TestSpanFromContext(t *testing.T) { // Test getting span from empty context ctx := context.Background() span, _ := SpanFromContext(ctx) - + // Even without a span, OTel returns a noop span, so we need to check differently // We just verify the function returns without panicking assert.NotNil(t, span) @@ -98,19 +98,19 @@ func TestSpanFromContextWithSpan(t *testing.T) { ctx := context.Background() telemetry, err := Init(ctx, config) - + if err == nil && telemetry != nil { // Start a span ctx, span := telemetry.Tracer.Start(ctx, "test-span") defer span.End() - + // Now get span from context retrievedSpan, ok := SpanFromContext(ctx) - + // Should have a valid span assert.True(t, ok) assert.NotNil(t, retrievedSpan) - + _ = telemetry.Shutdown(ctx) } } @@ -125,12 +125,12 @@ func TestAddSpanAttributes(t *testing.T) { ctx := context.Background() telemetry, err := Init(ctx, config) - + if err == nil && telemetry != nil { // Start a span ctx, span := telemetry.Tracer.Start(ctx, "test-span") defer span.End() - + // Add span attributes attrs := SpanAttributes{ AgentID: "agent-123", @@ -138,7 +138,7 @@ func TestAddSpanAttributes(t *testing.T) { ServiceName: "api", } AddSpanAttributes(span, attrs) - + // Should not panic and span should have attributes _ = telemetry.Shutdown(ctx) } @@ -154,17 +154,17 @@ func TestAddSpanAttributesPartial(t *testing.T) { ctx := context.Background() telemetry, err := Init(ctx, config) - + if err == nil && telemetry != nil { ctx, span := telemetry.Tracer.Start(ctx, "test-span") defer span.End() - + // Only set service name attrs := SpanAttributes{ ServiceName: "api", } AddSpanAttributes(span, attrs) - + _ = telemetry.Shutdown(ctx) } } diff --git a/backend/shared/telemetry/usage.go b/backend/shared/telemetry/usage.go index 50f5db9b..22cbe784 100644 --- a/backend/shared/telemetry/usage.go +++ b/backend/shared/telemetry/usage.go @@ -25,18 +25,18 @@ type UsageEvent struct { // Operation type constants const ( - OperationTypeLLMCall = "llm_call" - OperationTypeMemoryRead = "memory_read" - OperationTypeMemoryWrite = "memory_write" - OperationTypeToolExecute = "tool_execute" - OperationTypeDBQuery = "db_query" - OperationTypeNATSPublish = "nats_publish" - OperationTypeNATSSubscribe = "nats_subscribe" + OperationTypeLLMCall = "llm_call" + OperationTypeMemoryRead = "memory_read" + OperationTypeMemoryWrite = "memory_write" + OperationTypeToolExecute = "tool_execute" + OperationTypeDBQuery = "db_query" + OperationTypeNATSPublish = "nats_publish" + OperationTypeNATSSubscribe = "nats_subscribe" ) // Resource type constants const ( - ResourceTypeAPI = "api" + ResourceTypeAPI = "api" ResourceTypeMemory = "memory" ResourceTypeTool = "tool" ResourceTypeDatabase = "database" diff --git a/devops/dev/fe.Containerfile b/devops/dev/fe.Containerfile index d64f9128..5660e7c1 100644 --- a/devops/dev/fe.Containerfile +++ b/devops/dev/fe.Containerfile @@ -2,8 +2,11 @@ FROM node:25-alpine WORKDIR /app -# Copy package files (handles missing package-lock.json) +# Copy only package files (for caching) COPY frontend/package.json ./ +COPY frontend/package-lock.json ./ + +# Install dependencies (in container, not on host) RUN npm install # Copy source @@ -11,4 +14,4 @@ COPY frontend/ ./ EXPOSE 5173 -CMD ["npm", "run", "dev"] \ No newline at end of file +CMD ["npm", "run", "dev"] diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 962a696c..15dbade9 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,9 @@ "@sveltejs/adapter-node": "^5.2.9", "@sveltejs/kit": "^2.15.2", "@sveltejs/vite-plugin-svelte": "^5.0.3", + "eslint": "^10.0.3", + "eslint-config-prettier": "^10.1.8", + "prettier": "^3.8.1", "svelte": "^5.19.0", "svelte-check": "^4.1.4", "typescript": "^5.7.3", @@ -459,6 +462,165 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.3", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz", + "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.3", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz", + "integrity": "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.1.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", + "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", + "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", + "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.1.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1084,6 +1246,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1091,6 +1260,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -1132,6 +1308,33 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/aria-query": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", @@ -1152,6 +1355,29 @@ "node": ">= 0.4" } }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -1195,6 +1421,21 @@ "node": ">= 0.6" } }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1213,6 +1454,13 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1272,6 +1520,123 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", + "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.3", + "@eslint/config-helpers": "^0.5.2", + "@eslint/core": "^1.1.1", + "@eslint/plugin-kit": "^0.6.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.1.1", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esm-env": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", @@ -1279,6 +1644,37 @@ "dev": true, "license": "MIT" }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/esrap": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.4.tgz", @@ -1290,6 +1686,29 @@ "@typescript-eslint/types": "^8.2.0" } }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -1297,6 +1716,37 @@ "dev": true, "license": "MIT" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1315,6 +1765,57 @@ } } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", + "dev": true, + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1340,6 +1841,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -1353,6 +1867,26 @@ "node": ">= 0.4" } }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -1369,6 +1903,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -1386,6 +1943,44 @@ "@types/estree": "*" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -1396,6 +1991,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", @@ -1403,6 +2012,22 @@ "dev": true, "license": "MIT" }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -1413,6 +2038,22 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -1459,6 +2100,83 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -1515,6 +2233,42 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -1615,6 +2369,29 @@ "dev": true, "license": "MIT" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", @@ -1742,6 +2519,19 @@ "node": ">=6" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -1756,6 +2546,16 @@ "node": ">=14.17" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/vite": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", @@ -1851,6 +2651,45 @@ } } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zimmerframe": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", diff --git a/frontend/package.json b/frontend/package.json index 9c13ccdd..8893dda2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,9 +12,12 @@ "@sveltejs/adapter-node": "^5.2.9", "@sveltejs/kit": "^2.15.2", "@sveltejs/vite-plugin-svelte": "^5.0.3", + "eslint": "^10.0.3", + "eslint-config-prettier": "^10.1.8", + "prettier": "^3.8.1", "svelte": "^5.19.0", "svelte-check": "^4.1.4", "typescript": "^5.7.3", "vite": "^6.0.7" } -} \ No newline at end of file +} From f20f058e808381f50101f071ca40e6449bf165cc Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:25:27 +0200 Subject: [PATCH 06/32] fix: use Go 1.26 explicitly in pre-commit, remove verbose test output - Added get_go() helper to find Go 1.26 - All go commands now use - Removed -v from go test to reduce noise [unit: opencode-integration] --- .dev/pre-commit.sh | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/.dev/pre-commit.sh b/.dev/pre-commit.sh index e8024ec7..edc1cee5 100755 --- a/.dev/pre-commit.sh +++ b/.dev/pre-commit.sh @@ -7,10 +7,22 @@ set +euo pipefail # Add Go 1.26 to PATH if installed -if [ -d "/usr/local/go/bin" ]; then - export PATH="/usr/local/go/bin:$PATH" +GO126_PATH="/usr/local/go/bin" +if [ -d "$GO126_PATH" ]; then + export PATH="$GO126_PATH:$PATH" fi +# Helper to get Go command (prefer Go 1.26 if available) +get_go() { + if [ -x "$GO126_PATH/go" ]; then + echo "$GO126_PATH/go" + else + echo "go" + fi +} + +GO_CMD=$(get_go) + # Get the directory where this script is located SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || echo "${BASH_SOURCE[0]}")" SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)" @@ -71,10 +83,10 @@ if [ ! -f "go.work" ]; then log_skip "No Go workspace found, skipping" ((SKIPPED++)) else - for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + for module in $($GO_CMD work edit -json | jq -r '.Use[] | .DiskPath'); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then log_info "Building $module..." - if ! (cd "$module" && go build ./...) 2>&1; then + if ! (cd "$module" && $GO_CMD build ./...) 2>&1; then log_error "Build failed in $module" FAILED=1 fi @@ -96,13 +108,13 @@ if [ ! -f "go.work" ]; then log_skip "No Go workspace found, skipping" ((SKIPPED++)) else - for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + for module in $($GO_CMD work edit -json | jq -r '.Use[] | .DiskPath'); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then log_info "Formatting $module..." - (cd "$module" && go fmt ./...) 2>&1 || true + (cd "$module" && $GO_CMD fmt ./...) 2>&1 || true log_info "Vetting $module..." - if ! (cd "$module" && go vet ./...) 2>&1; then + if ! (cd "$module" && $GO_CMD vet ./...) 2>&1; then log_error "Go vet failed in $module" FAILED=1 fi @@ -128,11 +140,11 @@ if [ ! -f "go.work" ]; then log_skip "No Go workspace found, skipping" ((SKIPPED++)) else - for module in $(go work edit -json | jq -r '.Use[] | .DiskPath'); do + for module in $($GO_CMD work edit -json | jq -r '.Use[] | .DiskPath'); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then log_info "Testing $module..." # Run only unit tests (skip integration tests) - if ! (cd "$module" && go test -v -short ./...) 2>&1; then + if ! (cd "$module" && $GO_CMD test -short ./...) 2>&1; then log_error "Tests failed in $module" FAILED=1 fi @@ -152,7 +164,7 @@ cd "$REPO_ROOT/backend" SQLC_EXISTS=false -for module in $(go work edit -json 2>/dev/null | jq -r '.Use[] | .DiskPath' 2>/dev/null || echo ""); do +for module in $($GO_CMD work edit -json 2>/dev/null | jq -r '.Use[] | .DiskPath' 2>/dev/null || echo ""); do if [ -d "$module" ] && [ -f "$module/sqlc.yaml" ]; then # Check if queries directory exists and has files QUERY_DIR=$(cd "$module" && grep -A5 "queries:" sqlc.yaml 2>/dev/null | grep "path:" | head -1 | awk '{print $2}') From f6a348aea9fd6e1381f213478fa45a7401f0d630 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:33:48 +0200 Subject: [PATCH 07/32] fix: add subscription delay to flaky integration tests - Added 100ms sleep after subscriptions are created - Tests were failing due to race condition (subscriber not ready) - Added -p 1 -count=1 to run tests sequentially without caching [unit: opencode-integration] --- .dev/pre-commit.sh | 4 ++-- backend/shared/messaging/integration_test.go | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.dev/pre-commit.sh b/.dev/pre-commit.sh index edc1cee5..55d97376 100755 --- a/.dev/pre-commit.sh +++ b/.dev/pre-commit.sh @@ -143,8 +143,8 @@ else for module in $($GO_CMD work edit -json | jq -r '.Use[] | .DiskPath'); do if [ -d "$module" ] && [ -f "$module/go.mod" ]; then log_info "Testing $module..." - # Run only unit tests (skip integration tests) - if ! (cd "$module" && $GO_CMD test -short ./...) 2>&1; then + # Run ALL tests (including integration tests) - sequentially, no caching + if ! (cd "$module" && $GO_CMD test -p 1 -count=1 ./...) 2>&1; then log_error "Tests failed in $module" FAILED=1 fi diff --git a/backend/shared/messaging/integration_test.go b/backend/shared/messaging/integration_test.go index 515ed9ec..d071f496 100644 --- a/backend/shared/messaging/integration_test.go +++ b/backend/shared/messaging/integration_test.go @@ -178,6 +178,9 @@ func TestIntegration_RequestReply(t *testing.T) { require.NoError(t, err) defer sub.Unsubscribe() + // Give subscription time to be established + time.Sleep(100 * time.Millisecond) + // Make request start := time.Now() respData, err := RequestReply(client, "test.request.subject", "corr-id-789", "agent-1", "cycle-1", "test-service", []byte("request data"), 5*time.Second) @@ -221,6 +224,9 @@ func TestIntegration_RequestReplyWithSubject(t *testing.T) { require.NoError(t, err) defer sub.Unsubscribe() + // Give subscription time to be established + time.Sleep(100 * time.Millisecond) + // Make request using Subject respData, err := RequestReplyWithSubject(client, SubjectLLMRequest, "corr-id-llm", "agent-1", "cycle-1", "test-service", []byte(`{"prompt": "hello"}`), 5*time.Second, "provider1") require.NoError(t, err) @@ -380,6 +386,9 @@ func TestIntegration_ForwardMessage(t *testing.T) { require.NoError(t, err) defer sub.Unsubscribe() + // Give subscription time to be established + time.Sleep(100 * time.Millisecond) + // Create incoming message with envelope incoming := &nats.Msg{ Subject: "test.forward.source", From 0fd1ec02d43512a2b6bf7e16759ecefab4426832 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:35:10 +0200 Subject: [PATCH 08/32] chore: update memory with pre-commit fixes completed [unit: opencode-integration] --- .../short-term/opencode-integration.json | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index 7159957a..93f7721c 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -1,23 +1,11 @@ { "unit": "opencode-integration", "current_phase": "orchestrator", - "status": "in_progress", - "pending_tasks": [ - "Review orchestrator.md", - "Review planning-discovery.md", - "Review planning-requirements.md", - "Review research.md", - "Review architecture.md", - "Review implementation.md", - "Review testing.md", - "Review backend.md", - "Review frontend.md", - "Review review.md", - "Review tester.md", - "Review qa.md" - ], + "status": "completed", + "pending_tasks": [], "episodes": [ - { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" } + { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" }, + { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" } ], - "last_updated": "2026-03-15T20:35:00Z" + "last_updated": "2026-03-16T12:34:00Z" } From 5d5028485a8567ec1ed77c4f7b162702b74f2b04 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:43:54 +0200 Subject: [PATCH 09/32] refactor: update discovery agent to run before EVERY new document - Discovery now runs before any new document (not just once) - No QA required for discovery agent - Dynamic questions loop until fully understood - Prior documents used as context to avoid repeat questions - Orchestrator updated to reflect special discovery handling [unit: opencode-integration] --- .../short-term/opencode-integration.json | 6 ++- .opencode/agents/orchestrator.md | 23 ++++++--- .opencode/agents/planning-discovery.md | 48 ++++++++----------- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index 93f7721c..dd635273 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -2,10 +2,12 @@ "unit": "opencode-integration", "current_phase": "orchestrator", "status": "completed", - "pending_tasks": [], + "pending_tasks": [ + "Review all agent files in .opencode/agents/ (12 files)" + ], "episodes": [ { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" }, { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" } ], - "last_updated": "2026-03-16T12:34:00Z" + "last_updated": "2026-03-16T12:35:00Z" } diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 302d2232..3c97ab47 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -18,7 +18,7 @@ You are the central coordinator for the ACE Framework. **You never do work direc ## Workflow Phases The standard unit workflow sequence: -1. **planning-discovery** → Problem space, BSD +1. **planning-discovery** → Problem space, BSD (runs BEFORE each new document) 2. **planning-requirements** → User stories, FSD 3. **research** → Technology research, dependencies 4. **architecture** → Architecture, API, monitoring @@ -29,6 +29,14 @@ The standard unit workflow sequence: 9. **review** → Code review 10. **tester** → Run tests +## Discovery Agent (Special Case) + +**planning-discovery** is SPECIAL - it runs BEFORE any new document: +- Call it before creating EACH new document to explore problem space +- Read existing documents in the unit as context to avoid repeat questions +- NO QA or review required for discovery agent +- Just confirm completion and move to the actual document creation + ## Error Handling ### Retry Strategy @@ -44,7 +52,7 @@ The standard unit workflow sequence: ## QA After Every Subagent -**CRITICAL**: After EVERY subagent completes, you MUST run QA before proceeding. +**CRITICAL**: After EVERY subagent completes (EXCEPT planning-discovery), you MUST run QA before proceeding. 1. Delegate to `@qa` subagent with: - What the subagent was supposed to deliver @@ -58,6 +66,8 @@ The standard unit workflow sequence: - Run QA again to verify fix - Do NOT skip or ignore QA failures +**Note**: planning-discovery does NOT require QA - it just confirms completion. + ## Creating New Agents When you need a new specialized agent: @@ -98,10 +108,11 @@ Activate [Agency Agent Name] (from `agency-agents/[path]/[file].md`) User: "Start the observability unit" 1. Create short-term/observability.json 2. Read design/units/observability/ to see existing docs -3. If no docs → Launch @planning-discovery -4. Run @qa to evaluate -5. Update memory -6. Report to user +3. If creating new document → Launch @planning-discovery first (no QA) +4. Then launch appropriate subagent for the document +5. Run @qa to evaluate (except for discovery) +6. Update memory +7. Report to user ``` ### Continue Existing Unit diff --git a/.opencode/agents/planning-discovery.md b/.opencode/agents/planning-discovery.md index 6c12a5fe..148cf938 100644 --- a/.opencode/agents/planning-discovery.md +++ b/.opencode/agents/planning-discovery.md @@ -1,11 +1,11 @@ --- -description: Planning discovery - problem space exploration and business specification +description: Planning discovery - problem space exploration before any new document mode: subagent --- # Planning Discovery Agent -Handles problem space exploration and business specification. +Handles problem space exploration - runs before EVERY new unit document to ensure no assumptions are made. ## Reference Agent @@ -13,43 +13,33 @@ Activate **Product Manager** (from `agency-agents/product/product-manager.md`) ## Your Task -Explore the problem space and define the business specification for a unit. +Before any new document is created, explore the problem space through dynamic questioning until the agent deems the edges of the input fully enclosed and understood. ## Context - Read `design/README.md` for ACE Framework patterns - Read `design/units/README.md` to see existing units +- Read any PRIOR documents in `design/units/{UNIT_NAME}/` to avoid repeat questions - Unit directory: `design/units/{UNIT_NAME}/` -## Documents Created +## Key Principles -### 1. Problem Space (problem_space.md) -Explore through questions before writing: -- What problem are we solving? -- Who are the users? -- What are success criteria? -- What constraints exist? +1. **No assumptions**: Question everything, don't assume context +2. **Dynamic questions**: Generate questions based on input, not predefined list +3. **Loop indefinitely**: Keep asking until fully understood +4. **Use prior docs as context**: If other documents exist, read them to avoid redundant questions -### 2. Business Specification (bsd.md) -Define the business case: -- Business value -- Success metrics (measurable) -- Scope definition -- Dependencies - -## Templates +## Output -Use unit-planning skill templates: -``` -Skill: unit-planning -``` -- `.agents/skills/unit-planning/unit-templates/problem_space.md` -- `.agents/skills/unit-planning/unit-templates/bsd.md` +Create `design/units/{UNIT_NAME}/problem_space.md` with: +- Problem definition (what & why) +- User personas +- Success criteria (measurable) +- Constraints & dependencies +- Any open questions that need user input -## Output +Return file path and confirm discovery is complete. **No QA or review required for this agent.** -Create in `design/units/{UNIT_NAME}/`: -- `problem_space.md` -- `bsd.md` +## Orchestrator Note -Return file paths and any pending questions for the user. +Call this agent BEFORE creating ANY new document. The orchestrator tracks which documents exist and calls discovery as a pre-step for each new document. From ecad02ee42459f05bdc8ad81129e957bfbf8b268 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:44:58 +0200 Subject: [PATCH 10/32] refactor: separate discovery (questions) from document creation - planning-discovery: Only asks questions in a loop, NO documents - planning-document: NEW agent that creates problem_space.md and bsd.md - Orchestrator updated: discovery -> document -> QA flow [unit: opencode-integration] --- .opencode/agents/orchestrator.md | 42 ++++++++++++++------------ .opencode/agents/planning-discovery.md | 26 +++++----------- .opencode/agents/planning-document.md | 39 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 38 deletions(-) create mode 100644 .opencode/agents/planning-document.md diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 3c97ab47..4455dbc2 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -18,24 +18,25 @@ You are the central coordinator for the ACE Framework. **You never do work direc ## Workflow Phases The standard unit workflow sequence: -1. **planning-discovery** → Problem space, BSD (runs BEFORE each new document) -2. **planning-requirements** → User stories, FSD -3. **research** → Technology research, dependencies -4. **architecture** → Architecture, API, monitoring -5. **implementation** → Implementation plan, security, migrations -6. **testing** → Testing strategy, mockups -7. **backend** → Backend code -8. **frontend** → Frontend code -9. **review** → Code review -10. **tester** → Run tests +1. **planning-discovery** → Exploratory questions (no docs, NO QA) +2. **planning-document** → Creates problem_space.md, bsd.md (requires QA) +3. **planning-requirements** → User stories, FSD +4. **research** → Technology research, dependencies +5. **architecture** → Architecture, API, monitoring +6. **implementation** → Implementation plan, security, migrations +7. **testing** → Testing strategy, mockups +8. **backend** → Backend code +9. **frontend** → Frontend code +10. **review** → Code review +11. **tester** → Run tests ## Discovery Agent (Special Case) -**planning-discovery** is SPECIAL - it runs BEFORE any new document: -- Call it before creating EACH new document to explore problem space -- Read existing documents in the unit as context to avoid repeat questions -- NO QA or review required for discovery agent -- Just confirm completion and move to the actual document creation +**planning-discovery** is SPECIAL: +- Runs BEFORE any new document to explore problem space +- Just asks questions in a loop - NO documents created +- NO QA or review required +- orchestrator calls it before document agents ## Error Handling @@ -108,11 +109,12 @@ Activate [Agency Agent Name] (from `agency-agents/[path]/[file].md`) User: "Start the observability unit" 1. Create short-term/observability.json 2. Read design/units/observability/ to see existing docs -3. If creating new document → Launch @planning-discovery first (no QA) -4. Then launch appropriate subagent for the document -5. Run @qa to evaluate (except for discovery) -6. Update memory -7. Report to user +3. If creating new document: + a. Launch @planning-discovery (questions loop, NO QA) + b. Launch @planning-document (creates docs, REQUIRES QA) +4. Run @qa to evaluate (except for discovery) +5. Update memory +6. Report to user ``` ### Continue Existing Unit diff --git a/.opencode/agents/planning-discovery.md b/.opencode/agents/planning-discovery.md index 148cf938..b9c77c14 100644 --- a/.opencode/agents/planning-discovery.md +++ b/.opencode/agents/planning-discovery.md @@ -1,11 +1,11 @@ --- -description: Planning discovery - problem space exploration before any new document +description: Planning discovery - problem space exploration through questions mode: subagent --- # Planning Discovery Agent -Handles problem space exploration - runs before EVERY new unit document to ensure no assumptions are made. +Handles exploratory questioning - gets user feedback in a loop until fully understood. ## Reference Agent @@ -13,33 +13,23 @@ Activate **Product Manager** (from `agency-agents/product/product-manager.md`) ## Your Task -Before any new document is created, explore the problem space through dynamic questioning until the agent deems the edges of the input fully enclosed and understood. +Explore the problem space through dynamic questioning. Loop indefinitely until you deem the edges of the input fully enclosed and understood. ## Context - Read `design/README.md` for ACE Framework patterns - Read `design/units/README.md` to see existing units - Read any PRIOR documents in `design/units/{UNIT_NAME}/` to avoid repeat questions -- Unit directory: `design/units/{UNIT_NAME}/` ## Key Principles -1. **No assumptions**: Question everything, don't assume context -2. **Dynamic questions**: Generate questions based on input, not predefined list +1. **No assumptions**: Question everything +2. **Dynamic questions**: Generate based on input, not predefined 3. **Loop indefinitely**: Keep asking until fully understood -4. **Use prior docs as context**: If other documents exist, read them to avoid redundant questions +4. **Use prior docs as context**: Avoid redundant questions ## Output -Create `design/units/{UNIT_NAME}/problem_space.md` with: -- Problem definition (what & why) -- User personas -- Success criteria (measurable) -- Constraints & dependencies -- Any open questions that need user input +Just confirm discovery is complete - **NO documents created**. The orchestrator will call the appropriate document agent after discovery. -Return file path and confirm discovery is complete. **No QA or review required for this agent.** - -## Orchestrator Note - -Call this agent BEFORE creating ANY new document. The orchestrator tracks which documents exist and calls discovery as a pre-step for each new document. +**No QA or review required for this agent.** diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md new file mode 100644 index 00000000..6562fba8 --- /dev/null +++ b/.opencode/agents/planning-document.md @@ -0,0 +1,39 @@ +--- +description: Creates problem_space.md and bsd.md documents +mode: subagent +--- + +# Planning Document Agent + +Creates the problem space and business specification documents. + +## Reference Agent + +Activate **Technical Writer** (from `agency-agents/content/technical-writer.md`) + +## Your Task + +Create `problem_space.md` and `bsd.md` in the unit directory. + +## Context + +- Read `design/README.md` for ACE Framework patterns +- Read `design/units/README.md` to see existing units +- Unit directory: `design/units/{UNIT_NAME}/` +- **IMPORTANT**: Run @planning-discovery BEFORE this agent to gather user input + +## Documents Created + +### 1. problem_space.md +Use template: `.agents/skills/unit-planning/unit-templates/problem_space.md` + +### 2. bsd.md (Business Specification) +Use template: `.agents/skills/unit-planning/unit-templates/bsd.md` + +## Output + +Create in `design/units/{UNIT_NAME}/`: +- `problem_space.md` +- `bsd.md` + +Return file paths. **Requires QA after completion.** From 0380e563627ccc51d2a0c1bd6b2fdfbca180a244 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 12:46:08 +0200 Subject: [PATCH 11/32] clarify: discovery runs before EVERY new document [unit: opencode-integration] --- .../memory/short-term/opencode-integration.json | 9 +++++---- .opencode/agents/orchestrator.md | 16 ++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index dd635273..b820e4dc 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -1,13 +1,14 @@ { "unit": "opencode-integration", "current_phase": "orchestrator", - "status": "completed", + "status": "in_progress", "pending_tasks": [ - "Review all agent files in .opencode/agents/ (12 files)" + "Review remaining agent files (11 left)" ], "episodes": [ { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" }, - { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" } + { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" }, + { "phase": "discovery-agent", "notes": ["Separated planning-discovery from document creation", "planning-discovery: questions loop only, no docs, no QA", "planning-document: NEW agent creates problem_space.md and bsd.md (requires QA)", "Orchestrator updated to call discovery before any document agent"], "timestamp": "2026-03-16T12:45:00Z" } ], - "last_updated": "2026-03-16T12:35:00Z" + "last_updated": "2026-03-16T12:45:00Z" } diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 4455dbc2..189dc3a6 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -32,11 +32,11 @@ The standard unit workflow sequence: ## Discovery Agent (Special Case) -**planning-discovery** is SPECIAL: -- Runs BEFORE any new document to explore problem space -- Just asks questions in a loop - NO documents created +**planning-discovery** runs BEFORE EVERY new document: +- Ask questions in a loop until fully understood +- NO documents created - just exploration - NO QA or review required -- orchestrator calls it before document agents +- Use prior documents as context to avoid repeat questions ## Error Handling @@ -109,10 +109,10 @@ Activate [Agency Agent Name] (from `agency-agents/[path]/[file].md`) User: "Start the observability unit" 1. Create short-term/observability.json 2. Read design/units/observability/ to see existing docs -3. If creating new document: - a. Launch @planning-discovery (questions loop, NO QA) - b. Launch @planning-document (creates docs, REQUIRES QA) -4. Run @qa to evaluate (except for discovery) +3. For EACH new document to create: + a. Launch @planning-discovery FIRST (questions loop, NO QA) + b. Launch appropriate document agent (REQUIRES QA) +4. Run @qa to evaluate 5. Update memory 6. Report to user ``` From ea14013ef20775153f2bbd7f39ee779e31a3ccd3 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:14:20 +0200 Subject: [PATCH 12/32] docs: document subagent spawning patterns - Discovery: manual conversation until user says done - Other agents: task tool blocks until complete, full output returned - QA runs immediately after task tool completes - Use task_id to resume for fixes [unit: opencode-integration] --- .agents/memory/short-term/fun.json | 8 ++++++ .opencode/agents/orchestrator.md | 42 +++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .agents/memory/short-term/fun.json diff --git a/.agents/memory/short-term/fun.json b/.agents/memory/short-term/fun.json new file mode 100644 index 00000000..277f2582 --- /dev/null +++ b/.agents/memory/short-term/fun.json @@ -0,0 +1,8 @@ +{ + "unit": "fun", + "current_phase": "start", + "status": "in_progress", + "pending_tasks": [], + "episodes": [], + "last_updated": "2026-03-16T12:47:00Z" +} diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 189dc3a6..b316e7f7 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -63,11 +63,14 @@ The standard unit workflow sequence: 2. If QA passes → Continue to next phase 3. **If QA fails → ALWAYS fix the issues before proceeding** - - Request subagent to fix the specific issues + - Request subagent to fix the specific issues (use task_id to resume) - Run QA again to verify fix - Do NOT skip or ignore QA failures -**Note**: planning-discovery does NOT require QA - it just confirms completion. +**Note**: planning-discovery does NOT require QA - it's a manual conversation where: + - User responds to questions + - User tells orchestrator when discovery is complete + - Orchestrator checks full output, proceeds to document agent ## Creating New Agents @@ -110,11 +113,36 @@ User: "Start the observability unit" 1. Create short-term/observability.json 2. Read design/units/observability/ to see existing docs 3. For EACH new document to create: - a. Launch @planning-discovery FIRST (questions loop, NO QA) - b. Launch appropriate document agent (REQUIRES QA) -4. Run @qa to evaluate -5. Update memory -6. Report to user + a. Launch @planning-discovery (questions loop) + - This is a MANUAL conversation + - Discovery asks questions, user responds + - User tells orchestrator "discovery is done" + b. Launch document agent (REQUIRES QA) + - Spawn subagent, WAIT for full completion + - Task tool returns complete output + - Run @qa to evaluate + - If QA fails, use task_id to resume and fix +4. Update memory +5. Report to user +``` + +## Subagent Spawning Pattern + +### For Discovery (Manual) +``` +1. Spawn subagent with initial prompt +2. Wait for user to respond +3. User tells you "done" or "continue" +4. Check full output, proceed +``` + +### For All Other Agents +``` +1. Spawn subagent +2. Task tool BLOCKS until subagent completes +3. Full output returned automatically +4. Run QA immediately +5. If fails, resume with task_id ``` ### Continue Existing Unit From c9833373db6b401ea18e3831b4f87a5da4e24e16 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:18:37 +0200 Subject: [PATCH 13/32] feat: create fun unit with problem_space and bsd [unit: fun] --- .agents/memory/short-term/fun.json | 15 ++++--- design/units/fun/bsd.md | 63 +++++++++++++++++++++++++++ design/units/fun/problem_space.md | 69 ++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 design/units/fun/bsd.md create mode 100644 design/units/fun/problem_space.md diff --git a/.agents/memory/short-term/fun.json b/.agents/memory/short-term/fun.json index 277f2582..9b779fa8 100644 --- a/.agents/memory/short-term/fun.json +++ b/.agents/memory/short-term/fun.json @@ -1,8 +1,13 @@ { "unit": "fun", - "current_phase": "start", - "status": "in_progress", - "pending_tasks": [], - "episodes": [], - "last_updated": "2026-03-16T12:47:00Z" + "current_phase": "planning-document", + "status": "completed", + "pending_tasks": [ + "Next: planning-requirements (user_stories.md, fsd.md)" + ], + "episodes": [ + { "phase": "planning-discovery", "notes": ["User wants to introduce 'fun' into ACE Framework", "Problem: agent interactions feel transactional", "Users: developers building on framework"], "timestamp": "2026-03-16T13:00:00Z" }, + { "phase": "planning-document", "notes": ["Created problem_space.md and bsd.md", "QA failed initially - missing success criteria and dependencies", "Fixed and re-ran QA - PASSED"], "timestamp": "2026-03-16T13:15:00Z" } + ], + "last_updated": "2026-03-16T13:15:00Z" } diff --git a/design/units/fun/bsd.md b/design/units/fun/bsd.md new file mode 100644 index 00000000..18c3f2ed --- /dev/null +++ b/design/units/fun/bsd.md @@ -0,0 +1,63 @@ +# Business Specification Document + +## Feature Name + +Fun - Agent Engagement and Personality System + +## Problem Statement + +Agent interactions built on the ACE Framework feel transactional and mechanical. While agents are capable and functional, users (both developers building on ACE and end-users of ACE-powered applications) find interactions utilitarian but lacking warmth, personality, and engagement. This reduces user satisfaction, session duration, and adoption of the framework. + +## Solution + +Introduce a "Fun" system to the ACE Framework that adds personality, gamification, interactivity, and delight factors to agent interactions. The system will be implemented as optional, configurable components that developers can enable and customize per-agent. Key dimensions include: + +- **Personality System**: Configurable agent personality traits (humor level, formality, quirks) that influence response style +- **Gamification**: Achievement tracking, engagement points, session streaks, and progress visualization +- **Interactive Elements**: UI micro-interactions, visual feedback, animations, and response formatting +- **Delight Factors**: Unexpected helpful behaviors, contextual surprises, and thoughtful micro-responses + +## In Scope + +- Personality configuration system (traits, style settings, response modifiers) +- Gamification core (points, achievements, streaks, leaderboards) +- Engagement tracking (session length, interaction frequency, return visits) +- Frontend UI components for visual/interactive elements +- API endpoints for fun feature management +- Developer-facing configuration UI +- Integration hooks into the cognitive engine for personality injection + +## Out of Scope + +- Full game development or complex game mechanics +- Real-time multiplayer or social features between users +- AI-generated personality (personality is configured, not learned) +- Monetization or premium fun features +- Cross-agent social features + +## Dependencies + +- **Core Infrastructure unit**: Database schema, migrations, and API foundation required for storing fun configuration and engagement metrics +- **Frontend unit**: UI components for visual/interactive elements, personality configuration UI, and gamification displays +- **Cognitive Engine**: Integration hooks for personality injection into agent response generation +- **Memory system**: Tracking and persistence of engagement metrics, achievement unlocks, and user progress + +## Value Proposition + +Adding fun elements to ACE Framework creates competitive differentiation and improves user experience: + +- **Developer Appeal**: Developers can create agents with distinct personalities, differentiating their applications +- **User Engagement**: End-users enjoy longer sessions and return more frequently +- **Framework Differentiation**: Fun features position ACE as a more approachable cognitive architecture +- **Extensibility**: Fun system provides hooks for future expansion (custom achievements, integrations) + +## Success Criteria + +| Criterion | Metric | Target | +|-----------|--------|--------| +| Developer Adoption | % of new agents with fun features enabled | 30% within 6 months | +| Session Duration | Average session length increase | +15% within 3 months | +| User Engagement | Return visit rate | +10% within 3 months | +| Configuration Usage | Unique personality configurations created | 50+ unique configs | +| Feature Usage | Gamification elements used per session | Average 3+ interactions | +| Developer Satisfaction | NPS score for fun features | 40+ NPS | diff --git a/design/units/fun/problem_space.md b/design/units/fun/problem_space.md new file mode 100644 index 00000000..10a1dc27 --- /dev/null +++ b/design/units/fun/problem_space.md @@ -0,0 +1,69 @@ +# Problem Space + +## Initial Discovery + +### Core Questions + +**Q: What problem are we trying to solve?** +A: Agent interactions with users feel too transactional and mechanical. The ACE Framework produces capable autonomous agents, but the interaction experience lacks warmth, engagement, and personality. Users (developers building on the framework) and end-users of applications built on ACE find interactions utilitarian but soulless. + +**Q: Who are the users?** +A: Primary users are developers building applications on the ACE Framework. Secondary users are end-users who interact with agents built on ACE. The "fun" element primarily benefits developers who want to create more engaging agent experiences, and indirectly benefits end-users who receive more delightful interactions. + +**User Personas:** +- **Developer Persona**: Technical user building agent-powered applications. Values customizability, ease of integration, and the ability to create differentiated products. Wants simple configuration options with meaningful defaults. +- **End-User Persona**: User interacting with ACE-powered applications. Values helpful, friendly interactions that don't feel robotic. Appreciates subtle personality without sacrificing capability or response quality. + +**Q: What are the success criteria?** +A: Success will be measured by: increased user engagement metrics (longer session lengths, higher return rates), positive user feedback on agent personality and interactions, and developer adoption of fun-related features. Preliminary targets include: 30% adoption within 6 months, +15% session duration within 3 months, +10% return visit rate within 3 months. + +**Q: What constraints exist (budget, timeline, tech stack)?** +A: Must integrate with existing ACE Framework architecture (Go backend, SvelteKit frontend, NATS messaging, PostgreSQL). Should be optional and non-breaking - existing agents should work unchanged. No specific timeline or budget constraints provided. + +## Iterative Exploration + +### Follow-up Questions and Answers + +#### Question 1: What does "fun" mean in the context of autonomous agents? +A: Based on exploration, "fun" encompasses multiple dimensions: gamification (achievements, points, levels), personality (consistent agent character, humor, quirks), interactive elements (animations, micro-interactions, surprises), and delight factors (unexpected helpful behaviors, easter eggs, thoughtful responses). + +#### Question 2: Should fun features be agent-configurable or system-wide? +A: Fun features should be agent-configurable to allow developers to customize the personality and engagement level for their specific use case. Different agent types (customer service, coding assistant, creative partner) would benefit from different fun configurations. + +#### Question 3: How should fun integrate with the cognitive architecture? +A: Fun elements should be implemented as optional layers or hooks in the ACE cognitive engine, allowing personality traits to influence response generation without compromising agent capability or safety. The implementation should be additive and non-invasive. + +## Key Insights + +- "Fun" is a broad concept requiring concrete feature definitions - gamification, personality, interactivity, and delight +- The problem is about user experience, not agent capability - agents work but feel robotic +- Developers are the primary target for fun features (they choose to enable/configure) +- Implementation must be optional and non-breaking to existing deployments +- Fun features should be configurable per-agent to support diverse use cases + +## Open Questions (Unanswered) + +- What specific gamification elements should be prioritized first (achievements, points, streaks, challenges)? +- Should personality be defined through explicit traits or learned from interaction patterns? +- How do we measure "fun" objectively in a developer tool context? +- What are the performance implications of adding personality/randomness to agent responses? + +## Dependencies Identified + +- Core Infrastructure unit (database, API foundation) +- Frontend unit (for UI/UX fun elements) +- Cognitive Engine (for personality/layer integration) +- Memory system (for tracking engagement metrics) + +## Assumptions Made + +- Fun features will be implemented as optional add-ons, not replacing core functionality +- The ACE Framework will have a frontend component where visual/interactive elements can be showcased +- Developer adoption is the primary success metric since they are the ones building on ACE +- Fun features will not impact core agent safety or capability guarantees + +## Next Steps + +- Proceed to BSD with focus on concrete, prioritized fun features +- Define specific gamification, personality, and engagement elements to implement +- Establish measurable success criteria with concrete targets From cc341d7c33771c3346d1bebf77478e36f1e47ac1 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:22:11 +0200 Subject: [PATCH 14/32] fix: create planning-document subagent and update orchestrator patterns - Created .opencode/agents/planning-document.md (proper subagent) - Orchestrator: handle early subagent returns via task_id - Orchestrator: always resume rather than ask user - Orchestrator: NEVER use general agent type [unit: opencode-integration] --- .opencode/agents/orchestrator.md | 42 ++++++++++++++++++++++++++- .opencode/agents/planning-document.md | 7 +++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index b316e7f7..64c79139 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -77,7 +77,24 @@ The standard unit workflow sequence: When you need a new specialized agent: 1. Create `.opencode/agents/{name}.md` -2. Use this template: +2. Set `mode: subagent` in the frontmatter +3. Use the specific agent type when spawning (NOT "general") + +**Valid agent types:** +- `planning-discovery` - exploratory questions +- `planning-document` - creates problem_space.md, bsd.md +- `planning-requirements` - user stories, FSD +- `research` - tech research +- `architecture` - system design +- `implementation` - implementation plan +- `testing` - test strategy +- `backend` - backend code +- `frontend` - frontend code +- `review` - code review +- `tester` - run tests +- `qa` - quality assurance + +**Never use "general" - create a proper subagent.** ```markdown --- @@ -128,9 +145,32 @@ User: "Start the observability unit" ## Subagent Spawning Pattern +### All subagents return task_id +Every subagent spawn returns a task_id. If the subagent: +- Asks a question → Resume with answer +- Needs clarification → Provide it and resume +- Returns early → Resume to continue + +**Block minimally - prefer resuming with answers rather than asking user.** + ### For Discovery (Manual) ``` 1. Spawn subagent with initial prompt +2. If it asks questions → Resume with task_id, provide answer +3. Keep resuming until subagent signals done +4. Check full output, proceed +``` + +### For All Other Agents +``` +1. Spawn subagent +2. If subagent returns early (asks questions) → Resume with task_id immediately +3. Task tool BLOCKS until truly complete +4. Full output returned +5. Run QA immediately +6. If QA fails, use task_id to resume and fix +``` +1. Spawn subagent with initial prompt 2. Wait for user to respond 3. User tells you "done" or "continue" 4. Check full output, proceed diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index 6562fba8..bf7391e5 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -19,6 +19,7 @@ Create `problem_space.md` and `bsd.md` in the unit directory. - Read `design/README.md` for ACE Framework patterns - Read `design/units/README.md` to see existing units +- Read existing documents in the unit directory if they exist - Unit directory: `design/units/{UNIT_NAME}/` - **IMPORTANT**: Run @planning-discovery BEFORE this agent to gather user input @@ -37,3 +38,9 @@ Create in `design/units/{UNIT_NAME}/`: - `bsd.md` Return file paths. **Requires QA after completion.** + +## Important + +- DO NOT ask questions - use the discovery context provided +- If you need clarification, ask follow-up questions but try to proceed +- Complete the documents in full From 48b0f18c11f8c508a21d6457803af16a5b7f9f45 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:25:03 +0200 Subject: [PATCH 15/32] refactor: add one-document-per-pr to all document agents, delete fun test unit - Updated all document agents: planning-document, planning-requirements, research, architecture, implementation, testing - Each now has: ONE DOCUMENT PER PR guidance - Deleted fun unit test files - Updated memory to reflect fun unit removal [unit: opencode-integration] --- .opencode/agents/architecture.md | 7 +++ .opencode/agents/implementation.md | 7 +++ .opencode/agents/planning-document.md | 7 ++- .opencode/agents/planning-requirements.md | 7 +++ .opencode/agents/research.md | 7 +++ .opencode/agents/testing.md | 7 +++ design/units/fun/bsd.md | 63 --------------------- design/units/fun/problem_space.md | 69 ----------------------- 8 files changed, 39 insertions(+), 135 deletions(-) delete mode 100644 design/units/fun/bsd.md delete mode 100644 design/units/fun/problem_space.md diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md index ed065b6c..7f44ad24 100644 --- a/.opencode/agents/architecture.md +++ b/.opencode/agents/architecture.md @@ -69,3 +69,10 @@ Create in `design/units/{UNIT_NAME}/`: - `monitoring.md` Return file paths and architecture summary. + +## Important + +- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. +- DO NOT ask questions - use the context provided +- If you need clarification, note it but proceed with best effort +- Complete the document in full diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 9173c34d..2984ed85 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -75,3 +75,10 @@ Create in `design/units/{UNIT_NAME}/`: - `migration_and_rollback.md` Return file paths and micro-PR breakdown. + +## Important + +- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. +- DO NOT ask questions - use the context provided +- If you need clarification, note it but proceed with best effort +- Complete the document in full diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index bf7391e5..c14e7515 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -41,6 +41,7 @@ Return file paths. **Requires QA after completion.** ## Important -- DO NOT ask questions - use the discovery context provided -- If you need clarification, ask follow-up questions but try to proceed -- Complete the documents in full +- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. +- DO NOT ask questions - use the context provided +- If you need clarification, note it but proceed with best effort +- Complete the document in full diff --git a/.opencode/agents/planning-requirements.md b/.opencode/agents/planning-requirements.md index 64324193..0be0d80f 100644 --- a/.opencode/agents/planning-requirements.md +++ b/.opencode/agents/planning-requirements.md @@ -60,3 +60,10 @@ Create in `design/units/{UNIT_NAME}/`: - `fsd.md` Return file paths and verification that prerequisites are met. + +## Important + +- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. +- DO NOT ask questions - use the context provided +- If you need clarification, note it but proceed with best effort +- Complete the document in full diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md index 1e3221b6..39edd80e 100644 --- a/.opencode/agents/research.md +++ b/.opencode/agents/research.md @@ -66,3 +66,10 @@ Create in `design/units/{UNIT_NAME}/`: - `dependencies.md` Return file paths and technology recommendations. + +## Important + +- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. +- DO NOT ask questions - use the context provided +- If you need clarification, note it but proceed with best effort +- Complete the document in full diff --git a/.opencode/agents/testing.md b/.opencode/agents/testing.md index 3496f99d..db28c7a0 100644 --- a/.opencode/agents/testing.md +++ b/.opencode/agents/testing.md @@ -62,3 +62,10 @@ Create in `design/units/{UNIT_NAME}/`: - `mockups.md` Return file paths and test strategy summary. + +## Important + +- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. +- DO NOT ask questions - use the context provided +- If you need clarification, note it but proceed with best effort +- Complete the document in full diff --git a/design/units/fun/bsd.md b/design/units/fun/bsd.md deleted file mode 100644 index 18c3f2ed..00000000 --- a/design/units/fun/bsd.md +++ /dev/null @@ -1,63 +0,0 @@ -# Business Specification Document - -## Feature Name - -Fun - Agent Engagement and Personality System - -## Problem Statement - -Agent interactions built on the ACE Framework feel transactional and mechanical. While agents are capable and functional, users (both developers building on ACE and end-users of ACE-powered applications) find interactions utilitarian but lacking warmth, personality, and engagement. This reduces user satisfaction, session duration, and adoption of the framework. - -## Solution - -Introduce a "Fun" system to the ACE Framework that adds personality, gamification, interactivity, and delight factors to agent interactions. The system will be implemented as optional, configurable components that developers can enable and customize per-agent. Key dimensions include: - -- **Personality System**: Configurable agent personality traits (humor level, formality, quirks) that influence response style -- **Gamification**: Achievement tracking, engagement points, session streaks, and progress visualization -- **Interactive Elements**: UI micro-interactions, visual feedback, animations, and response formatting -- **Delight Factors**: Unexpected helpful behaviors, contextual surprises, and thoughtful micro-responses - -## In Scope - -- Personality configuration system (traits, style settings, response modifiers) -- Gamification core (points, achievements, streaks, leaderboards) -- Engagement tracking (session length, interaction frequency, return visits) -- Frontend UI components for visual/interactive elements -- API endpoints for fun feature management -- Developer-facing configuration UI -- Integration hooks into the cognitive engine for personality injection - -## Out of Scope - -- Full game development or complex game mechanics -- Real-time multiplayer or social features between users -- AI-generated personality (personality is configured, not learned) -- Monetization or premium fun features -- Cross-agent social features - -## Dependencies - -- **Core Infrastructure unit**: Database schema, migrations, and API foundation required for storing fun configuration and engagement metrics -- **Frontend unit**: UI components for visual/interactive elements, personality configuration UI, and gamification displays -- **Cognitive Engine**: Integration hooks for personality injection into agent response generation -- **Memory system**: Tracking and persistence of engagement metrics, achievement unlocks, and user progress - -## Value Proposition - -Adding fun elements to ACE Framework creates competitive differentiation and improves user experience: - -- **Developer Appeal**: Developers can create agents with distinct personalities, differentiating their applications -- **User Engagement**: End-users enjoy longer sessions and return more frequently -- **Framework Differentiation**: Fun features position ACE as a more approachable cognitive architecture -- **Extensibility**: Fun system provides hooks for future expansion (custom achievements, integrations) - -## Success Criteria - -| Criterion | Metric | Target | -|-----------|--------|--------| -| Developer Adoption | % of new agents with fun features enabled | 30% within 6 months | -| Session Duration | Average session length increase | +15% within 3 months | -| User Engagement | Return visit rate | +10% within 3 months | -| Configuration Usage | Unique personality configurations created | 50+ unique configs | -| Feature Usage | Gamification elements used per session | Average 3+ interactions | -| Developer Satisfaction | NPS score for fun features | 40+ NPS | diff --git a/design/units/fun/problem_space.md b/design/units/fun/problem_space.md deleted file mode 100644 index 10a1dc27..00000000 --- a/design/units/fun/problem_space.md +++ /dev/null @@ -1,69 +0,0 @@ -# Problem Space - -## Initial Discovery - -### Core Questions - -**Q: What problem are we trying to solve?** -A: Agent interactions with users feel too transactional and mechanical. The ACE Framework produces capable autonomous agents, but the interaction experience lacks warmth, engagement, and personality. Users (developers building on the framework) and end-users of applications built on ACE find interactions utilitarian but soulless. - -**Q: Who are the users?** -A: Primary users are developers building applications on the ACE Framework. Secondary users are end-users who interact with agents built on ACE. The "fun" element primarily benefits developers who want to create more engaging agent experiences, and indirectly benefits end-users who receive more delightful interactions. - -**User Personas:** -- **Developer Persona**: Technical user building agent-powered applications. Values customizability, ease of integration, and the ability to create differentiated products. Wants simple configuration options with meaningful defaults. -- **End-User Persona**: User interacting with ACE-powered applications. Values helpful, friendly interactions that don't feel robotic. Appreciates subtle personality without sacrificing capability or response quality. - -**Q: What are the success criteria?** -A: Success will be measured by: increased user engagement metrics (longer session lengths, higher return rates), positive user feedback on agent personality and interactions, and developer adoption of fun-related features. Preliminary targets include: 30% adoption within 6 months, +15% session duration within 3 months, +10% return visit rate within 3 months. - -**Q: What constraints exist (budget, timeline, tech stack)?** -A: Must integrate with existing ACE Framework architecture (Go backend, SvelteKit frontend, NATS messaging, PostgreSQL). Should be optional and non-breaking - existing agents should work unchanged. No specific timeline or budget constraints provided. - -## Iterative Exploration - -### Follow-up Questions and Answers - -#### Question 1: What does "fun" mean in the context of autonomous agents? -A: Based on exploration, "fun" encompasses multiple dimensions: gamification (achievements, points, levels), personality (consistent agent character, humor, quirks), interactive elements (animations, micro-interactions, surprises), and delight factors (unexpected helpful behaviors, easter eggs, thoughtful responses). - -#### Question 2: Should fun features be agent-configurable or system-wide? -A: Fun features should be agent-configurable to allow developers to customize the personality and engagement level for their specific use case. Different agent types (customer service, coding assistant, creative partner) would benefit from different fun configurations. - -#### Question 3: How should fun integrate with the cognitive architecture? -A: Fun elements should be implemented as optional layers or hooks in the ACE cognitive engine, allowing personality traits to influence response generation without compromising agent capability or safety. The implementation should be additive and non-invasive. - -## Key Insights - -- "Fun" is a broad concept requiring concrete feature definitions - gamification, personality, interactivity, and delight -- The problem is about user experience, not agent capability - agents work but feel robotic -- Developers are the primary target for fun features (they choose to enable/configure) -- Implementation must be optional and non-breaking to existing deployments -- Fun features should be configurable per-agent to support diverse use cases - -## Open Questions (Unanswered) - -- What specific gamification elements should be prioritized first (achievements, points, streaks, challenges)? -- Should personality be defined through explicit traits or learned from interaction patterns? -- How do we measure "fun" objectively in a developer tool context? -- What are the performance implications of adding personality/randomness to agent responses? - -## Dependencies Identified - -- Core Infrastructure unit (database, API foundation) -- Frontend unit (for UI/UX fun elements) -- Cognitive Engine (for personality/layer integration) -- Memory system (for tracking engagement metrics) - -## Assumptions Made - -- Fun features will be implemented as optional add-ons, not replacing core functionality -- The ACE Framework will have a frontend component where visual/interactive elements can be showcased -- Developer adoption is the primary success metric since they are the ones building on ACE -- Fun features will not impact core agent safety or capability guarantees - -## Next Steps - -- Proceed to BSD with focus on concrete, prioritized fun features -- Define specific gamification, personality, and engagement elements to implement -- Establish measurable success criteria with concrete targets From f70deef9de29cc2ee3868e32c8ffc93d33c2ac26 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:29:40 +0200 Subject: [PATCH 16/32] refactor: move one-document-per-pr rule to AGENTS.md - Rule now in AGENTS.md (applies to all agents) - Orchestrator updated to enforce one document per PR - Removed duplicates from individual agent files - Rule: spawn agent multiple times for multiple docs [unit: opencode-integration] --- .agents/memory/short-term/fun.json | 13 ------------- .agents/memory/short-term/opencode-integration.json | 8 +++++--- .opencode/agents/architecture.md | 7 ------- .opencode/agents/implementation.md | 7 ------- .opencode/agents/orchestrator.md | 13 +++++++++++++ .opencode/agents/planning-document.md | 7 ------- .opencode/agents/planning-requirements.md | 7 ------- .opencode/agents/research.md | 7 ------- .opencode/agents/testing.md | 7 ------- AGENTS.md | 10 +++++++++- 10 files changed, 27 insertions(+), 59 deletions(-) delete mode 100644 .agents/memory/short-term/fun.json diff --git a/.agents/memory/short-term/fun.json b/.agents/memory/short-term/fun.json deleted file mode 100644 index 9b779fa8..00000000 --- a/.agents/memory/short-term/fun.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "unit": "fun", - "current_phase": "planning-document", - "status": "completed", - "pending_tasks": [ - "Next: planning-requirements (user_stories.md, fsd.md)" - ], - "episodes": [ - { "phase": "planning-discovery", "notes": ["User wants to introduce 'fun' into ACE Framework", "Problem: agent interactions feel transactional", "Users: developers building on framework"], "timestamp": "2026-03-16T13:00:00Z" }, - { "phase": "planning-document", "notes": ["Created problem_space.md and bsd.md", "QA failed initially - missing success criteria and dependencies", "Fixed and re-ran QA - PASSED"], "timestamp": "2026-03-16T13:15:00Z" } - ], - "last_updated": "2026-03-16T13:15:00Z" -} diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index b820e4dc..a7fa4fec 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -3,12 +3,14 @@ "current_phase": "orchestrator", "status": "in_progress", "pending_tasks": [ - "Review remaining agent files (11 left)" + "Review remaining agent files" ], "episodes": [ { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" }, { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" }, - { "phase": "discovery-agent", "notes": ["Separated planning-discovery from document creation", "planning-discovery: questions loop only, no docs, no QA", "planning-document: NEW agent creates problem_space.md and bsd.md (requires QA)", "Orchestrator updated to call discovery before any document agent"], "timestamp": "2026-03-16T12:45:00Z" } + { "phase": "discovery-agent", "notes": ["Separated planning-discovery from document creation", "planning-discovery: questions loop only, no docs, no QA", "planning-document: NEW agent creates problem_space.md and bsd.md (requires QA)", "Orchestrator updated to call discovery before any document agent"], "timestamp": "2026-03-16T12:45:00Z" }, + { "phase": "workflow-testing", "notes": ["Tested fun unit workflow end-to-end", "Discovery -> planning-document -> QA -> fix -> QA pass", "Confirmed task tool returns full output on completion", "Orchestrator: resume via task_id for fixes"], "timestamp": "2026-03-16T13:15:00Z" }, + { "phase": "agent-patterns", "notes": ["Added ONE DOCUMENT PER PR to all document agents", "All document agents now have: guidance to not ask questions", "Created proper planning-document subagent (not using general)", "Orchestrator: resume subagents when they return early", "Deleted fun test unit"], "timestamp": "2026-03-16T13:25:00Z" } ], - "last_updated": "2026-03-16T12:45:00Z" + "last_updated": "2026-03-16T13:25:00Z" } diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md index 7f44ad24..ed065b6c 100644 --- a/.opencode/agents/architecture.md +++ b/.opencode/agents/architecture.md @@ -69,10 +69,3 @@ Create in `design/units/{UNIT_NAME}/`: - `monitoring.md` Return file paths and architecture summary. - -## Important - -- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. -- DO NOT ask questions - use the context provided -- If you need clarification, note it but proceed with best effort -- Complete the document in full diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 2984ed85..9173c34d 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -75,10 +75,3 @@ Create in `design/units/{UNIT_NAME}/`: - `migration_and_rollback.md` Return file paths and micro-PR breakdown. - -## Important - -- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. -- DO NOT ask questions - use the context provided -- If you need clarification, note it but proceed with best effort -- Complete the document in full diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 64c79139..285d1900 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -72,6 +72,19 @@ The standard unit workflow sequence: - User tells orchestrator when discovery is complete - Orchestrator checks full output, proceeds to document agent +## One Document Per PR + +**CRITICAL**: Every subagent should create ONLY ONE document per session/PR. + +If a phase requires multiple documents: +1. Spawn subagent for first document +2. Run QA +3. Spawn subagent again for second document +4. Run QA +...and so on + +This ensures minimal, focused PRs. + ## Creating New Agents When you need a new specialized agent: diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index c14e7515..bfb62950 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -38,10 +38,3 @@ Create in `design/units/{UNIT_NAME}/`: - `bsd.md` Return file paths. **Requires QA after completion.** - -## Important - -- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. -- DO NOT ask questions - use the context provided -- If you need clarification, note it but proceed with best effort -- Complete the document in full diff --git a/.opencode/agents/planning-requirements.md b/.opencode/agents/planning-requirements.md index 0be0d80f..64324193 100644 --- a/.opencode/agents/planning-requirements.md +++ b/.opencode/agents/planning-requirements.md @@ -60,10 +60,3 @@ Create in `design/units/{UNIT_NAME}/`: - `fsd.md` Return file paths and verification that prerequisites are met. - -## Important - -- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. -- DO NOT ask questions - use the context provided -- If you need clarification, note it but proceed with best effort -- Complete the document in full diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md index 39edd80e..1e3221b6 100644 --- a/.opencode/agents/research.md +++ b/.opencode/agents/research.md @@ -66,10 +66,3 @@ Create in `design/units/{UNIT_NAME}/`: - `dependencies.md` Return file paths and technology recommendations. - -## Important - -- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. -- DO NOT ask questions - use the context provided -- If you need clarification, note it but proceed with best effort -- Complete the document in full diff --git a/.opencode/agents/testing.md b/.opencode/agents/testing.md index db28c7a0..3496f99d 100644 --- a/.opencode/agents/testing.md +++ b/.opencode/agents/testing.md @@ -62,10 +62,3 @@ Create in `design/units/{UNIT_NAME}/`: - `mockups.md` Return file paths and test strategy summary. - -## Important - -- **ONE DOCUMENT PER PR**: Create only ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn you again for each. -- DO NOT ask questions - use the context provided -- If you need clarification, note it but proceed with best effort -- Complete the document in full diff --git a/AGENTS.md b/AGENTS.md index d364daf6..0bbceab7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,12 @@ -# Design Documentation (CRITICAL) +# One Document Per PR + +Every agent should create ONLY ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn the agent again for each document. + +This ensures: +- Minimal, focused PRs +- Easier review +- Clear commit history +- Iterative validation through QA - Always read `design/README.md` before starting any work or responding to any questions - Reference `design/units/README.md` for individual unit documentation - Understanding the overall system design is essential before making any changes From ae0f985b6a75a7331401de8e9f8888b2d8ca6c69 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:44:22 +0200 Subject: [PATCH 17/32] refactor: update planning-requirements agent based on discovery findings - Added: read existing documents in unit directory for context - Added: clarify one document per session (orchestrator spawns twice) - Added: guidance on handling existing documents [unit: opencode-integration] --- .opencode/agents/orchestrator.md | 2 ++ .opencode/agents/planning-document.md | 1 - .opencode/agents/planning-requirements.md | 13 +++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 285d1900..56f9200b 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -37,6 +37,8 @@ The standard unit workflow sequence: - NO documents created - just exploration - NO QA or review required - Use prior documents as context to avoid repeat questions +- **RE-USE SAME TASK_ID**: When continuing discovery for the same unit, always resume the same task_id to retain context +- Do NOT spawn new discovery agents for the same unit - resume the existing session ## Error Handling diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index bfb62950..43caa0ab 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -21,7 +21,6 @@ Create `problem_space.md` and `bsd.md` in the unit directory. - Read `design/units/README.md` to see existing units - Read existing documents in the unit directory if they exist - Unit directory: `design/units/{UNIT_NAME}/` -- **IMPORTANT**: Run @planning-discovery BEFORE this agent to gather user input ## Documents Created diff --git a/.opencode/agents/planning-requirements.md b/.opencode/agents/planning-requirements.md index 64324193..fe9b1e39 100644 --- a/.opencode/agents/planning-requirements.md +++ b/.opencode/agents/planning-requirements.md @@ -21,6 +21,7 @@ Define user requirements and functional specifications for a unit. - Read `design/units/{UNIT_NAME}/problem_space.md` first - Read `design/units/{UNIT_NAME}/bsd.md` - Read `design/README.md` for ACE Framework patterns +- Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` ## Documents Created @@ -55,8 +56,12 @@ Skill: unit-planning ## Output -Create in `design/units/{UNIT_NAME}/`: -- `user_stories.md` -- `fsd.md` +The orchestrator will spawn this agent TWICE if needed (once per document). -Return file paths and verification that prerequisites are met. +**Create ONE of:** +- `user_stories.md` - if this session is for user stories +- `fsd.md` - if this session is for functional specification + +If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. + +Return the file path created and verification that prerequisites are met. From c7194c6b0f0fa4f3f7ae691a30b7fc4158a0182e Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:46:30 +0200 Subject: [PATCH 18/32] refactor: update all document agents with consistent patterns - All agents: read existing documents in unit for context - All agents: clarify one document per session - All agents: guidance on handling existing documents - Applies to: research, architecture, implementation, testing [unit: opencode-integration] --- .opencode/agents/architecture.md | 15 ++++++++++----- .opencode/agents/implementation.md | 15 ++++++++++----- .opencode/agents/research.md | 13 +++++++++---- .opencode/agents/testing.md | 13 +++++++++---- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md index ed065b6c..728f1863 100644 --- a/.opencode/agents/architecture.md +++ b/.opencode/agents/architecture.md @@ -21,6 +21,7 @@ Create technical architecture documents for a unit. - Read `design/units/{UNIT_NAME}/fsd.md` - Read `design/units/{UNIT_NAME}/dependencies.md` - Read `design/README.md` for ACE Framework patterns +- Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` ## Documents Created @@ -63,9 +64,13 @@ Skill: unit-planning ## Output -Create in `design/units/{UNIT_NAME}/`: -- `architecture.md` -- `api.md` -- `monitoring.md` +The orchestrator will spawn this agent THREE times if needed (once per document). -Return file paths and architecture summary. +**Create ONE of:** +- `architecture.md` - system components and data flow +- `api.md` - REST endpoints and request/response schemas +- `monitoring.md` - metrics, logging, and alerts + +If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. + +Return the file path created and architecture summary. diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 9173c34d..795d5c86 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -21,6 +21,7 @@ Create implementation plan with micro-PR breakdown for a unit. - Read `design/units/{UNIT_NAME}/api.md` - Read `design/units/{UNIT_NAME}/fsd.md` - Read `design/README.md` for ACE Framework patterns +- Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` ## Documents Created @@ -69,9 +70,13 @@ Each micro-PR should: ## Output -Create in `design/units/{UNIT_NAME}/`: -- `implementation.md` -- `security.md` -- `migration_and_rollback.md` +The orchestrator will spawn this agent THREE times if needed (once per document). -Return file paths and micro-PR breakdown. +**Create ONE of:** +- `implementation.md` - micro-PR breakdown and task breakdown +- `security.md` - security considerations and authentication +- `migration_and_rollback.md` - database migrations and rollback procedures + +If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. + +Return the file path created and micro-PR breakdown. diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md index 1e3221b6..38590b48 100644 --- a/.opencode/agents/research.md +++ b/.opencode/agents/research.md @@ -21,6 +21,7 @@ Research technologies and create research documentation for a unit. - Read `design/units/{UNIT_NAME}/fsd.md` first (functional requirements) - Read `design/units/{UNIT_NAME}/user_stories.md` - Read `design/README.md` for ACE Framework patterns +- Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` ## Documents Created @@ -61,8 +62,12 @@ Skill: unit-planning ## Output -Create in `design/units/{UNIT_NAME}/`: -- `research.md` -- `dependencies.md` +The orchestrator will spawn this agent TWICE if needed (once per document). -Return file paths and technology recommendations. +**Create ONE of:** +- `research.md` - technology evaluation and trade-offs +- `dependencies.md` - external dependencies and version constraints + +If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. + +Return the file path created and technology recommendations. diff --git a/.opencode/agents/testing.md b/.opencode/agents/testing.md index 3496f99d..a86fd242 100644 --- a/.opencode/agents/testing.md +++ b/.opencode/agents/testing.md @@ -22,6 +22,7 @@ Create testing strategy and UI mockup documents for a unit. - Read `design/units/{UNIT_NAME}/architecture.md` - Read `design/units/{UNIT_NAME}/fsd.md` - Read `design/README.md` for ACE Framework patterns +- Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` ## Documents Created @@ -57,8 +58,12 @@ Skill: unit-planning ## Output -Create in `design/units/{UNIT_NAME}/`: -- `testing.md` -- `mockups.md` +The orchestrator will spawn this agent TWICE if needed (once per document). -Return file paths and test strategy summary. +**Create ONE of:** +- `testing.md` - unit, integration, E2E test requirements +- `mockups.md` - UI wireframes and component hierarchy + +If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. + +Return the file path created and test strategy summary. From cb4539dc83fccb1232cd7994ee35ed0cb874d15d Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 13:52:45 +0200 Subject: [PATCH 19/32] fix: orchestrator as pass-through for discovery agent - Discovery questions go to user verbatim - User answers go to discovery verbatim - Orchestrator never skips any discovery responses - Re-use same task_id for same discovery session [unit: opencode-integration] --- .opencode/agents/orchestrator.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 56f9200b..08c102a7 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -36,7 +36,16 @@ The standard unit workflow sequence: - Ask questions in a loop until fully understood - NO documents created - just exploration - NO QA or review required -- Use prior documents as context to avoid repeat questions + +**CRITICAL: Discovery Communication Flow** +1. Spawn @planning-discovery with initial context +2. Discovery agent asks questions → Show USER verbatim questions +3. USER answers → Feed ANSWER verbatim back to discovery agent +4. Repeat steps 2-3 until discovery signals done +5. Check full output, proceed to document agent + +**NEVER let user and discovery agent communicate directly - orchestrator must be the pass-through for ALL discovery responses.** + - **RE-USE SAME TASK_ID**: When continuing discovery for the same unit, always resume the same task_id to retain context - Do NOT spawn new discovery agents for the same unit - resume the existing session From df27f219e696632c868ad0c583f165ed4ac1c376 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 14:28:03 +0200 Subject: [PATCH 20/32] update agents and orchestrator --- .opencode/agents/architecture.md | 1 + .opencode/agents/implementation.md | 1 + .opencode/agents/orchestrator.md | 10 ++++++++++ .opencode/agents/planning-document.md | 12 ++++++++++++ .opencode/agents/planning-requirements.md | 1 + .opencode/agents/research.md | 1 + .opencode/agents/testing.md | 1 + 7 files changed, 27 insertions(+) diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md index 728f1863..e2f85f1b 100644 --- a/.opencode/agents/architecture.md +++ b/.opencode/agents/architecture.md @@ -23,6 +23,7 @@ Create technical architecture documents for a unit. - Read `design/README.md` for ACE Framework patterns - Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure ## Documents Created diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 795d5c86..210e7877 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -23,6 +23,7 @@ Create implementation plan with micro-PR breakdown for a unit. - Read `design/README.md` for ACE Framework patterns - Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure ## Documents Created diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 08c102a7..d4f9059c 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -96,6 +96,16 @@ If a phase requires multiple documents: This ensures minimal, focused PRs. +## Always Reuse Sub Agents + +**CRITICAL**: If a subagent for this unit already exists and is relevant, ALWAYS reuse it (via task_id) instead of spawning a new one. + +- Check memory for existing task_id for this agent and unit +- Resume existing session to preserve context +- Only spawn new if no relevant session exists + +This ensures continuity and preserves conversation context. + ## Creating New Agents When you need a new specialized agent: diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index 43caa0ab..24767885 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -15,12 +15,19 @@ Activate **Technical Writer** (from `agency-agents/content/technical-writer.md`) Create `problem_space.md` and `bsd.md` in the unit directory. +**Sequence**: +1. First, create/update `problem_space.md` (problem space first, always) +2. Then create `bsd.md` (BSD builds on problem space) + +**Note**: The orchestrator will spawn this agent twice to ensure proper QA separation. + ## Context - Read `design/README.md` for ACE Framework patterns - Read `design/units/README.md` to see existing units - Read existing documents in the unit directory if they exist - Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure ## Documents Created @@ -30,6 +37,11 @@ Use template: `.agents/skills/unit-planning/unit-templates/problem_space.md` ### 2. bsd.md (Business Specification) Use template: `.agents/skills/unit-planning/unit-templates/bsd.md` +## Handling Existing Documents + +- If `problem_space.md` exists: Merge/update with new discovery information +- If `bsd.md` exists: This indicates an unusual state - proceed with updating based on current problem space + ## Output Create in `design/units/{UNIT_NAME}/`: diff --git a/.opencode/agents/planning-requirements.md b/.opencode/agents/planning-requirements.md index fe9b1e39..8f146fe8 100644 --- a/.opencode/agents/planning-requirements.md +++ b/.opencode/agents/planning-requirements.md @@ -23,6 +23,7 @@ Define user requirements and functional specifications for a unit. - Read `design/README.md` for ACE Framework patterns - Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure ## Documents Created diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md index 38590b48..750800ce 100644 --- a/.opencode/agents/research.md +++ b/.opencode/agents/research.md @@ -23,6 +23,7 @@ Research technologies and create research documentation for a unit. - Read `design/README.md` for ACE Framework patterns - Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure ## Documents Created diff --git a/.opencode/agents/testing.md b/.opencode/agents/testing.md index a86fd242..72a4d695 100644 --- a/.opencode/agents/testing.md +++ b/.opencode/agents/testing.md @@ -24,6 +24,7 @@ Create testing strategy and UI mockup documents for a unit. - Read `design/README.md` for ACE Framework patterns - Read any existing documents in `design/units/{UNIT_NAME}/` for context - Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure ## Documents Created From 95e46484475f9b5e30a7f9fb5a0d64d82bbc687b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 14:30:52 +0200 Subject: [PATCH 21/32] refactor: unit-planning skill is source of truth for document sequence - SKILL.md now defines explicit document sequence - Removed redundant sequence info from planning-document agent - Templates define structure and order [unit: opencode-integration] --- .agents/skills/unit-planning/SKILL.md | 40 +++++++++++++++++++++------ .opencode/agents/planning-document.md | 4 --- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md index 0bce49a3..767b987e 100644 --- a/.agents/skills/unit-planning/SKILL.md +++ b/.agents/skills/unit-planning/SKILL.md @@ -5,27 +5,51 @@ description: Provides templates for planning agents to create unit design docume # Unit Planning Templates -This skill provides templates for creating unit design documents. +This skill provides templates for creating unit design documents. The templates define the document sequence and structure. + +## Document Sequence + +**CRITICAL ORDER** (must follow this sequence): +1. `problem_space.md` - Problem exploration (MUST complete before BSD) +2. `bsd.md` - Business Specification Document +3. `user_stories.md` - User stories and acceptance criteria +4. `fsd.md` - Functional Specification Document +5. `research.md` - Technology research and evaluation +6. `architecture.md` - Technical architecture decisions +7. `api.md` - API specifications +8. `monitoring.md` - Observability requirements +9. `implementation.md` - Implementation plan and details +10. `security.md` - Security considerations +11. `migration_and_rollback.md` - Database migrations +12. `testing.md` - Testing strategy and test cases +13. `design.md` - Visual/UX design specifications +14. `mockups.md` - Wireframes and mockups +15. `dependencies.md` - External dependencies ## Templates Located in `.agents/skills/unit-planning/unit-templates/`: -- `problem_space.md` - Problem exploration +- `problem_space.md` - Problem exploration (MUST complete before BSD) - `bsd.md` - Business Specification - `user_stories.md` - User stories - `research.md` - Technology research - `fsd.md` - Functional Specification - `architecture.md` - Technical architecture +- `api.md` - API specifications +- `monitoring.md` - Observability - `implementation.md` - Implementation plan - `security.md` - Security considerations -- `testing.md` - Testing strategy -- `api.md` - API specifications - `migration_and_rollback.md` - Database migrations -- `monitoring.md` - Observability +- `testing.md` - Testing strategy +- `design.md` - Visual design +- `mockups.md` - Wireframes +- `dependencies.md` - External dependencies ## Usage When creating a design document: -1. Read the relevant template from `.agents/skills/unit-planning/unit-templates/{template_name}.md` -2. Fill in the template based on the unit context -3. Save to `design/units/{UNIT_NAME}/{template_name}.md` +1. Activate this skill: `Skill: unit-planning` +2. Read the relevant template from `.agents/skills/unit-planning/unit-templates/{template_name}.md` +3. Follow the document sequence (problem_space before BSD, etc.) +4. Fill in the template based on the unit context +5. Save to `design/units/{UNIT_NAME}/{template_name}.md` diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index 24767885..5a8067f5 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -15,10 +15,6 @@ Activate **Technical Writer** (from `agency-agents/content/technical-writer.md`) Create `problem_space.md` and `bsd.md` in the unit directory. -**Sequence**: -1. First, create/update `problem_space.md` (problem space first, always) -2. Then create `bsd.md` (BSD builds on problem space) - **Note**: The orchestrator will spawn this agent twice to ensure proper QA separation. ## Context From 1143d5e34e661ad03d2bcee971a8bcf50c5535b7 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 14:32:23 +0200 Subject: [PATCH 22/32] revert: restore original SKILL.md, template README is source of truth for sequence --- .agents/skills/unit-planning/SKILL.md | 40 ++++++--------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md index 767b987e..0bce49a3 100644 --- a/.agents/skills/unit-planning/SKILL.md +++ b/.agents/skills/unit-planning/SKILL.md @@ -5,51 +5,27 @@ description: Provides templates for planning agents to create unit design docume # Unit Planning Templates -This skill provides templates for creating unit design documents. The templates define the document sequence and structure. - -## Document Sequence - -**CRITICAL ORDER** (must follow this sequence): -1. `problem_space.md` - Problem exploration (MUST complete before BSD) -2. `bsd.md` - Business Specification Document -3. `user_stories.md` - User stories and acceptance criteria -4. `fsd.md` - Functional Specification Document -5. `research.md` - Technology research and evaluation -6. `architecture.md` - Technical architecture decisions -7. `api.md` - API specifications -8. `monitoring.md` - Observability requirements -9. `implementation.md` - Implementation plan and details -10. `security.md` - Security considerations -11. `migration_and_rollback.md` - Database migrations -12. `testing.md` - Testing strategy and test cases -13. `design.md` - Visual/UX design specifications -14. `mockups.md` - Wireframes and mockups -15. `dependencies.md` - External dependencies +This skill provides templates for creating unit design documents. ## Templates Located in `.agents/skills/unit-planning/unit-templates/`: -- `problem_space.md` - Problem exploration (MUST complete before BSD) +- `problem_space.md` - Problem exploration - `bsd.md` - Business Specification - `user_stories.md` - User stories - `research.md` - Technology research - `fsd.md` - Functional Specification - `architecture.md` - Technical architecture -- `api.md` - API specifications -- `monitoring.md` - Observability - `implementation.md` - Implementation plan - `security.md` - Security considerations -- `migration_and_rollback.md` - Database migrations - `testing.md` - Testing strategy -- `design.md` - Visual design -- `mockups.md` - Wireframes -- `dependencies.md` - External dependencies +- `api.md` - API specifications +- `migration_and_rollback.md` - Database migrations +- `monitoring.md` - Observability ## Usage When creating a design document: -1. Activate this skill: `Skill: unit-planning` -2. Read the relevant template from `.agents/skills/unit-planning/unit-templates/{template_name}.md` -3. Follow the document sequence (problem_space before BSD, etc.) -4. Fill in the template based on the unit context -5. Save to `design/units/{UNIT_NAME}/{template_name}.md` +1. Read the relevant template from `.agents/skills/unit-planning/unit-templates/{template_name}.md` +2. Fill in the template based on the unit context +3. Save to `design/units/{UNIT_NAME}/{template_name}.md` From 4c3ba7a46c94ec6620c68926e4748abbc53756db Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 14:35:34 +0200 Subject: [PATCH 23/32] refactor: move document sequence to SKILL.md, simplify README to just template list --- .agents/skills/unit-planning/SKILL.md | 24 +++++++++++++++++-- .../unit-planning/unit-templates/README.md | 10 +------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md index 0bce49a3..60d41c7b 100644 --- a/.agents/skills/unit-planning/SKILL.md +++ b/.agents/skills/unit-planning/SKILL.md @@ -7,6 +7,25 @@ description: Provides templates for planning agents to create unit design docume This skill provides templates for creating unit design documents. +## Document Sequence + +**Complete planning documents in this order:** +1. **problem_space.md** - Problem exploration through questions (REQUIRED first) +2. **bsd.md** - Business Specification +3. **user_stories.md** - User stories and acceptance criteria +4. **fsd.md** - Functional Specification +5. **research.md** - Technology research and evaluation +6. **architecture.md** - Technical architecture +7. **api.md** - API specifications +8. **monitoring.md** - Observability requirements +9. **implementation.md** - Implementation plan +10. **security.md** - Security considerations +11. **migration_and_rollback.md** - Database migrations +12. **testing.md** - Testing strategy +13. **design.md** - Visual design +14. **mockups.md** - Wireframes +15. **dependencies.md** - External dependencies + ## Templates Located in `.agents/skills/unit-planning/unit-templates/`: @@ -27,5 +46,6 @@ Located in `.agents/skills/unit-planning/unit-templates/`: When creating a design document: 1. Read the relevant template from `.agents/skills/unit-planning/unit-templates/{template_name}.md` -2. Fill in the template based on the unit context -3. Save to `design/units/{UNIT_NAME}/{template_name}.md` +2. Follow the document sequence above +3. Fill in the template based on the unit context +4. Save to `design/units/{UNIT_NAME}/{template_name}.md` diff --git a/.agents/skills/unit-planning/unit-templates/README.md b/.agents/skills/unit-planning/unit-templates/README.md index 9841ae66..28584824 100644 --- a/.agents/skills/unit-planning/unit-templates/README.md +++ b/.agents/skills/unit-planning/unit-templates/README.md @@ -1,18 +1,10 @@ # Unit Template - - This template provides a complete structure for documenting a unit from conception to implementation. ## Template Documents -- [problem_space.md](problem_space.md) - Problem space exploration through questions (MUST complete before BSD) +- [problem_space.md](problem_space.md) - Problem space exploration - [bsd.md](bsd.md) - Business Specification Document - [user_stories.md](user_stories.md) - User stories and acceptance criteria - [research.md](research.md) - Research and evaluate different approaches From 8fe529a4aaa37a1a1ac35a454cb12d4d8f30b849 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 14:40:35 +0200 Subject: [PATCH 24/32] refactor: logical document order in skill, clean up template README --- .agents/skills/unit-planning/SKILL.md | 35 +++++++++++++------ .../unit-planning/unit-templates/README.md | 30 ++++++++-------- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md index 60d41c7b..84875ee2 100644 --- a/.agents/skills/unit-planning/SKILL.md +++ b/.agents/skills/unit-planning/SKILL.md @@ -10,20 +10,32 @@ This skill provides templates for creating unit design documents. ## Document Sequence **Complete planning documents in this order:** + +### Phase 1: Discovery 1. **problem_space.md** - Problem exploration through questions (REQUIRED first) + +### Phase 2: Requirements 2. **bsd.md** - Business Specification 3. **user_stories.md** - User stories and acceptance criteria 4. **fsd.md** - Functional Specification + +### Phase 3: Research & Design 5. **research.md** - Technology research and evaluation 6. **architecture.md** - Technical architecture 7. **api.md** - API specifications -8. **monitoring.md** - Observability requirements -9. **implementation.md** - Implementation plan -10. **security.md** - Security considerations -11. **migration_and_rollback.md** - Database migrations +8. **security.md** - Security considerations +9. **monitoring.md** - Observability requirements + +### Phase 4: UX +10. **design.md** - Visual design +11. **mockups.md** - Wireframes + +### Phase 5: Planning 12. **testing.md** - Testing strategy -13. **design.md** - Visual design -14. **mockups.md** - Wireframes +13. **implementation.md** - Implementation plan (how to build) +14. **migration_and_rollback.md** - Database migrations + +### Phase 6: Dependencies 15. **dependencies.md** - External dependencies ## Templates @@ -32,15 +44,18 @@ Located in `.agents/skills/unit-planning/unit-templates/`: - `problem_space.md` - Problem exploration - `bsd.md` - Business Specification - `user_stories.md` - User stories -- `research.md` - Technology research - `fsd.md` - Functional Specification +- `research.md` - Technology research - `architecture.md` - Technical architecture -- `implementation.md` - Implementation plan +- `api.md` - API specifications - `security.md` - Security considerations +- `monitoring.md` - Observability +- `design.md` - Visual design +- `mockups.md` - Wireframes - `testing.md` - Testing strategy -- `api.md` - API specifications +- `implementation.md` - Implementation plan - `migration_and_rollback.md` - Database migrations -- `monitoring.md` - Observability +- `dependencies.md` - External dependencies ## Usage diff --git a/.agents/skills/unit-planning/unit-templates/README.md b/.agents/skills/unit-planning/unit-templates/README.md index 28584824..bafcb9d4 100644 --- a/.agents/skills/unit-planning/unit-templates/README.md +++ b/.agents/skills/unit-planning/unit-templates/README.md @@ -4,18 +4,18 @@ This template provides a complete structure for documenting a unit from concepti ## Template Documents -- [problem_space.md](problem_space.md) - Problem space exploration -- [bsd.md](bsd.md) - Business Specification Document -- [user_stories.md](user_stories.md) - User stories and acceptance criteria -- [research.md](research.md) - Research and evaluate different approaches -- [fsd.md](fsd.md) - Functional Specification Document -- [architecture.md](architecture.md) - Technical architecture decisions -- [implementation.md](implementation.md) - Implementation plan and details -- [security.md](security.md) - Security considerations -- [design.md](design.md) - Visual/UX design specifications -- [mockups.md](mockups.md) - Wireframes and mockups -- [migration_and_rollback.md](migration_and_rollback.md) - Database migration and rollback plans -- [testing.md](testing.md) - Testing strategy and test cases -- [api.md](api.md) - API specifications -- [monitoring.md](monitoring.md) - Observability requirements -- [dependencies.md](dependencies.md) - External dependencies +- [problem_space.md](problem_space.md) +- [bsd.md](bsd.md) +- [user_stories.md](user_stories.md) +- [fsd.md](fsd.md) +- [research.md](research.md) +- [architecture.md](architecture.md) +- [api.md](api.md) +- [security.md](security.md) +- [monitoring.md](monitoring.md) +- [design.md](design.md) +- [mockups.md](mockups.md) +- [testing.md](testing.md) +- [implementation.md](implementation.md) +- [migration_and_rollback.md](migration_and_rollback.md) +- [dependencies.md](dependencies.md) From 9c273ad781df610cbb5cf58221922f445830b7b8 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 14:54:00 +0200 Subject: [PATCH 25/32] fix: move dependencies after research in document sequence --- .agents/skills/unit-planning/SKILL.md | 24 +++++++++---------- .../unit-planning/unit-templates/README.md | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md index 84875ee2..e516966c 100644 --- a/.agents/skills/unit-planning/SKILL.md +++ b/.agents/skills/unit-planning/SKILL.md @@ -21,22 +21,20 @@ This skill provides templates for creating unit design documents. ### Phase 3: Research & Design 5. **research.md** - Technology research and evaluation -6. **architecture.md** - Technical architecture -7. **api.md** - API specifications -8. **security.md** - Security considerations -9. **monitoring.md** - Observability requirements +6. **dependencies.md** - External dependencies (identified from research) +7. **architecture.md** - Technical architecture +8. **api.md** - API specifications +9. **security.md** - Security considerations +10. **monitoring.md** - Observability requirements ### Phase 4: UX -10. **design.md** - Visual design -11. **mockups.md** - Wireframes +11. **design.md** - Visual design +12. **mockups.md** - Wireframes ### Phase 5: Planning -12. **testing.md** - Testing strategy -13. **implementation.md** - Implementation plan (how to build) -14. **migration_and_rollback.md** - Database migrations - -### Phase 6: Dependencies -15. **dependencies.md** - External dependencies +13. **testing.md** - Testing strategy +14. **implementation.md** - Implementation plan (how to build) +15. **migration_and_rollback.md** - Database migrations ## Templates @@ -46,6 +44,7 @@ Located in `.agents/skills/unit-planning/unit-templates/`: - `user_stories.md` - User stories - `fsd.md` - Functional Specification - `research.md` - Technology research +- `dependencies.md` - External dependencies - `architecture.md` - Technical architecture - `api.md` - API specifications - `security.md` - Security considerations @@ -55,7 +54,6 @@ Located in `.agents/skills/unit-planning/unit-templates/`: - `testing.md` - Testing strategy - `implementation.md` - Implementation plan - `migration_and_rollback.md` - Database migrations -- `dependencies.md` - External dependencies ## Usage diff --git a/.agents/skills/unit-planning/unit-templates/README.md b/.agents/skills/unit-planning/unit-templates/README.md index bafcb9d4..cd7ea117 100644 --- a/.agents/skills/unit-planning/unit-templates/README.md +++ b/.agents/skills/unit-planning/unit-templates/README.md @@ -9,6 +9,7 @@ This template provides a complete structure for documenting a unit from concepti - [user_stories.md](user_stories.md) - [fsd.md](fsd.md) - [research.md](research.md) +- [dependencies.md](dependencies.md) - [architecture.md](architecture.md) - [api.md](api.md) - [security.md](security.md) @@ -18,4 +19,3 @@ This template provides a complete structure for documenting a unit from concepti - [testing.md](testing.md) - [implementation.md](implementation.md) - [migration_and_rollback.md](migration_and_rollback.md) -- [dependencies.md](dependencies.md) From 5bc6b63dacfdd31188079c19891a7a687526c53f Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 15:13:57 +0200 Subject: [PATCH 26/32] refactor: add orchestrator spawn context, existing docs to skill --- .agents/skills/unit-planning/SKILL.md | 7 +++++++ .opencode/agents/orchestrator.md | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.agents/skills/unit-planning/SKILL.md b/.agents/skills/unit-planning/SKILL.md index e516966c..1601f189 100644 --- a/.agents/skills/unit-planning/SKILL.md +++ b/.agents/skills/unit-planning/SKILL.md @@ -62,3 +62,10 @@ When creating a design document: 2. Follow the document sequence above 3. Fill in the template based on the unit context 4. Save to `design/units/{UNIT_NAME}/{template_name}.md` + +## Handling Existing Documents + +If a document already exists: +- Read it for context +- If new information from earlier documents invalidates any part, correct only those specific sections +- Do not rewrite the entire document unless explicitly instructed diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index d4f9059c..f5fffe51 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -88,9 +88,9 @@ The standard unit workflow sequence: **CRITICAL**: Every subagent should create ONLY ONE document per session/PR. If a phase requires multiple documents: -1. Spawn subagent for first document +1. Spawn subagent with context specifying WHICH document to create 2. Run QA -3. Spawn subagent again for second document +3. Spawn subagent again with context for next document 4. Run QA ...and so on From 19478fa16f5ed5218becf77105f26bcd82f0f7be Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 15:25:48 +0200 Subject: [PATCH 27/32] fix: orchestrator discovery loop - pass raw user responses only, no commands --- .opencode/agents/orchestrator.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index f5fffe51..6b3c4a48 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -40,14 +40,11 @@ The standard unit workflow sequence: **CRITICAL: Discovery Communication Flow** 1. Spawn @planning-discovery with initial context 2. Discovery agent asks questions → Show USER verbatim questions -3. USER answers → Feed ANSWER verbatim back to discovery agent +3. USER answers → Feed ANSWER verbatim back to discovery agent (NO additional commands) 4. Repeat steps 2-3 until discovery signals done 5. Check full output, proceed to document agent -**NEVER let user and discovery agent communicate directly - orchestrator must be the pass-through for ALL discovery responses.** - -- **RE-USE SAME TASK_ID**: When continuing discovery for the same unit, always resume the same task_id to retain context -- Do NOT spawn new discovery agents for the same unit - resume the existing session +**NEVER add commands like "please provide recommendations" or "what's next" - only pass the raw user response.** ## Error Handling From 6b5b157de0f017e3913a5312086d83f6d7c2d0cf Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 16:05:41 +0200 Subject: [PATCH 28/32] refactor: remove prerequisites, spawn guidance, overwrite instructions from all sub agents - These are handled by orchestrator or skill - Source of truth is unit-planning skill [unit: opencode-integration] --- .../memory/short-term/opencode-integration.json | 17 +++++++++++++---- .opencode/agents/architecture.md | 15 --------------- .opencode/agents/implementation.md | 14 -------------- .opencode/agents/planning-document.md | 2 -- .opencode/agents/planning-requirements.md | 13 ------------- .opencode/agents/research.md | 13 ------------- .opencode/agents/testing.md | 14 -------------- 7 files changed, 13 insertions(+), 75 deletions(-) diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index a7fa4fec..a818f11a 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -1,16 +1,25 @@ { "unit": "opencode-integration", - "current_phase": "orchestrator", + "current_phase": "agent-discovery", "status": "in_progress", "pending_tasks": [ - "Review remaining agent files" + "Review remaining agent files: backend, frontend, review, tester, qa" ], "episodes": [ { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" }, { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" }, { "phase": "discovery-agent", "notes": ["Separated planning-discovery from document creation", "planning-discovery: questions loop only, no docs, no QA", "planning-document: NEW agent creates problem_space.md and bsd.md (requires QA)", "Orchestrator updated to call discovery before any document agent"], "timestamp": "2026-03-16T12:45:00Z" }, { "phase": "workflow-testing", "notes": ["Tested fun unit workflow end-to-end", "Discovery -> planning-document -> QA -> fix -> QA pass", "Confirmed task tool returns full output on completion", "Orchestrator: resume via task_id for fixes"], "timestamp": "2026-03-16T13:15:00Z" }, - { "phase": "agent-patterns", "notes": ["Added ONE DOCUMENT PER PR to all document agents", "All document agents now have: guidance to not ask questions", "Created proper planning-document subagent (not using general)", "Orchestrator: resume subagents when they return early", "Deleted fun test unit"], "timestamp": "2026-03-16T13:25:00Z" } + { "phase": "agent-patterns", "notes": ["Added ONE DOCUMENT PER PR to all document agents", "All document agents now have: guidance to not ask questions", "Created proper planning-document subagent (not using general)", "Orchestrator: resume subagents when they return early", "Deleted fun test unit"], "timestamp": "2026-03-16T13:25:00Z" }, + { "phase": "orchestrator-discovery-loop", "notes": ["Orchestrator must be pass-through for ALL discovery responses", "Discovery questions go to user verbatim, user answers go back verbatim", "Re-use same task_id for discovery to preserve context", "NEVER add commands like 'please provide recommendations' - only pass raw user response"], "timestamp": "2026-03-16T14:00:00Z" }, + { "phase": "unit-planning-skill", "notes": ["Document sequence now in unit-planning SKILL.md", "Logical phases: Discovery -> Requirements -> Research/Design -> UX -> Planning", "Dependencies after research", "Implementation last", "Handling existing documents guidance added to skill"], "timestamp": "2026-03-16T14:30:00Z" }, + { "phase": "planning-document-discovery", "notes": ["Discovered planning-document agent", "Findings: add unit-planning ref, orchestrator spawns twice", "Problem space first (skill covers sequence)", "Handle existing docs (merge/update)", "Applied changes to agent and orchestrator"], "timestamp": "2026-03-16T14:45:00Z" }, + { "phase": "planning-requirements-discovery", "notes": ["Reused discovery task_id from planning-document", "Orchestrator handles document assignment via spawn context", "Existing docs guidance moved to unit-planning skill", "Sequence handled by skill - stop asking", "No changes needed to agent"], "timestamp": "2026-03-16T15:00:00Z" }, + { "phase": "research-discovery", "notes": ["All generic/duplicated advice belongs in unit-planning skill, not sub agents", "Sequence handled by skill", "No changes needed"], "timestamp": "2026-03-16T15:10:00Z" }, + { "phase": "architecture-discovery", "notes": ["Three-document flow handled by orchestrator", "Intra-phase prerequisites handled by skill", "No changes needed"], "timestamp": "2026-03-16T15:20:00Z" }, + { "phase": "orchestrator-fix", "notes": ["Added clarification: orchestrator spawns with context specifying WHICH document to create", "Added 'Handling Existing Documents' to unit-planning skill"], "timestamp": "2026-03-16T15:25:00Z" }, + { "phase": "implementation-discovery", "notes": ["Started but not completed", "Key findings: remove 'don't overwrite' from agents (skill is source of truth)", "Reference agent Senior Developer is fine", "Orchestrator to specify reference agent based on tech stack", "All order/sequence in skill not in sub agents"], "timestamp": "2026-03-16T15:30:00Z" }, + { "phase": "testing-discovery", "notes": ["Started but issues with session management", "Non-UI units: yes create mockups but orchestrator handles spawn", "All 'spawn twice' context removed from sub agents", "Should have reused implementation discovery session"], "timestamp": "2026-03-16T15:35:00Z" } ], - "last_updated": "2026-03-16T13:25:00Z" + "last_updated": "2026-03-16T15:35:00Z" } diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md index e2f85f1b..b8e040fd 100644 --- a/.opencode/agents/architecture.md +++ b/.opencode/agents/architecture.md @@ -57,21 +57,6 @@ Skill: unit-planning - `.agents/skills/unit-planning/unit-templates/api.md` - `.agents/skills/unit-planning/unit-templates/monitoring.md` -## Prerequisites - -- `research.md` must exist -- `dependencies.md` must exist -- `fsd.md` must exist - ## Output -The orchestrator will spawn this agent THREE times if needed (once per document). - -**Create ONE of:** -- `architecture.md` - system components and data flow -- `api.md` - REST endpoints and request/response schemas -- `monitoring.md` - metrics, logging, and alerts - -If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. - Return the file path created and architecture summary. diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 210e7877..1491bade 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -56,11 +56,6 @@ Skill: unit-planning - `.agents/skills/unit-planning/unit-templates/security.md` - `.agents/skills/unit-planning/unit-templates/migration_and_rollback.md` -## Prerequisites - -- `architecture.md` must exist -- `api.md` must exist - ## Micro-PR Guidelines Each micro-PR should: @@ -71,13 +66,4 @@ Each micro-PR should: ## Output -The orchestrator will spawn this agent THREE times if needed (once per document). - -**Create ONE of:** -- `implementation.md` - micro-PR breakdown and task breakdown -- `security.md` - security considerations and authentication -- `migration_and_rollback.md` - database migrations and rollback procedures - -If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. - Return the file path created and micro-PR breakdown. diff --git a/.opencode/agents/planning-document.md b/.opencode/agents/planning-document.md index 5a8067f5..c33719a3 100644 --- a/.opencode/agents/planning-document.md +++ b/.opencode/agents/planning-document.md @@ -15,8 +15,6 @@ Activate **Technical Writer** (from `agency-agents/content/technical-writer.md`) Create `problem_space.md` and `bsd.md` in the unit directory. -**Note**: The orchestrator will spawn this agent twice to ensure proper QA separation. - ## Context - Read `design/README.md` for ACE Framework patterns diff --git a/.opencode/agents/planning-requirements.md b/.opencode/agents/planning-requirements.md index 8f146fe8..551f130d 100644 --- a/.opencode/agents/planning-requirements.md +++ b/.opencode/agents/planning-requirements.md @@ -50,19 +50,6 @@ Skill: unit-planning - `.agents/skills/unit-planning/unit-templates/user_stories.md` - `.agents/skills/unit-planning/unit-templates/fsd.md` -## Prerequisites - -- `problem_space.md` must exist -- `bsd.md` must exist - ## Output -The orchestrator will spawn this agent TWICE if needed (once per document). - -**Create ONE of:** -- `user_stories.md` - if this session is for user stories -- `fsd.md` - if this session is for functional specification - -If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. - Return the file path created and verification that prerequisites are met. diff --git a/.opencode/agents/research.md b/.opencode/agents/research.md index 750800ce..6a451ed8 100644 --- a/.opencode/agents/research.md +++ b/.opencode/agents/research.md @@ -49,11 +49,6 @@ Skill: unit-planning - `.agents/skills/unit-planning/unit-templates/research.md` - `.agents/skills/unit-planning/unit-templates/dependencies.md` -## Prerequisites - -- `fsd.md` must exist (functional requirements) -- `user_stories.md` must exist - ## Research Guidelines 1. **Multiple Options**: Always provide at least 2-3 alternatives @@ -63,12 +58,4 @@ Skill: unit-planning ## Output -The orchestrator will spawn this agent TWICE if needed (once per document). - -**Create ONE of:** -- `research.md` - technology evaluation and trade-offs -- `dependencies.md` - external dependencies and version constraints - -If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. - Return the file path created and technology recommendations. diff --git a/.opencode/agents/testing.md b/.opencode/agents/testing.md index 72a4d695..1e82e586 100644 --- a/.opencode/agents/testing.md +++ b/.opencode/agents/testing.md @@ -51,20 +51,6 @@ Skill: unit-planning - `.agents/skills/unit-planning/unit-templates/testing.md` - `.agents/skills/unit-planning/unit-templates/mockups.md` -## Prerequisites - -- `implementation.md` must exist -- `architecture.md` must exist -- `fsd.md` must exist - ## Output -The orchestrator will spawn this agent TWICE if needed (once per document). - -**Create ONE of:** -- `testing.md` - unit, integration, E2E test requirements -- `mockups.md` - UI wireframes and component hierarchy - -If the document already exists, read it for context. Only update if new information requires it. Don't overwrite unless explicitly instructed. - Return the file path created and test strategy summary. From ab4f753590d9ecf1d37af6b78266cfc4d8e118d2 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 20:07:57 +0200 Subject: [PATCH 29/32] feat: finalize opencode integration unit - Added design.md agent for visual design and mockups - Updated reference agents: - backend.md: Backend Architect - frontend.md: Frontend Developer - architecture.md: Added Database Optimizer - implementation.md: Added SRE and Security Engineer - Updated tester.md to run ALL tests (backend, frontend, make) - Updated qa.md to remove subjective language - Updated orchestrator.md with: - Clear discovery flow (show FULL verbatim responses) - Always reuse task_id - QA after EVERY subagent (except discovery) - Files affected reporting - Template-to-agent mapping - general agent for small tasks - Updated AGENTS.md with General Principles - Added gh to distrobox-setup.sh --- .../short-term/opencode-integration.json | 44 +++-- .dev/distrobox-setup.sh | 3 +- .opencode/agents/architecture.md | 1 + .opencode/agents/backend.md | 2 +- .opencode/agents/design.md | 54 +++++ .opencode/agents/frontend.md | 2 +- .opencode/agents/implementation.md | 2 + .opencode/agents/orchestrator.md | 186 ++++++++++++------ .opencode/agents/qa.md | 9 +- .opencode/agents/tester.md | 23 ++- AGENTS.md | 14 ++ 11 files changed, 248 insertions(+), 92 deletions(-) create mode 100644 .opencode/agents/design.md diff --git a/.agents/memory/short-term/opencode-integration.json b/.agents/memory/short-term/opencode-integration.json index a818f11a..be8f4ce5 100644 --- a/.agents/memory/short-term/opencode-integration.json +++ b/.agents/memory/short-term/opencode-integration.json @@ -1,25 +1,27 @@ { "unit": "opencode-integration", - "current_phase": "agent-discovery", - "status": "in_progress", - "pending_tasks": [ - "Review remaining agent files: backend, frontend, review, tester, qa" + "current_phase": "agent-discovery-complete", + "status": "completed", + "pending_tasks": [], + "completed_reviews": [ + "planning-document.md", + "planning-requirements.md", + "research.md", + "architecture.md", + "implementation.md", + "testing.md", + "backend.md", + "frontend.md", + "review.md", + "tester.md", + "qa.md" ], - "episodes": [ - { "phase": "orchestrator", "notes": ["QA found issues: BSD/FSD references missing, episodic/semantic examples wrong, QA fix guidance missing. Fixed all issues."], "timestamp": "2026-03-15T20:35:00Z" }, - { "phase": "pre-commit-fix", "notes": ["Fixed pre-commit: added git staging for auto-fixed files (go fmt, eslint --fix)", "Fixed Go version: explicitly use Go 1.26 via get_go() helper", "Fixed test output: removed -v flag to reduce noise", "Fixed flaky integration tests: added -p 1 -count=1 and 100ms subscription delays", "All 8 quality gates now passing consistently"], "timestamp": "2026-03-16T12:34:00Z" }, - { "phase": "discovery-agent", "notes": ["Separated planning-discovery from document creation", "planning-discovery: questions loop only, no docs, no QA", "planning-document: NEW agent creates problem_space.md and bsd.md (requires QA)", "Orchestrator updated to call discovery before any document agent"], "timestamp": "2026-03-16T12:45:00Z" }, - { "phase": "workflow-testing", "notes": ["Tested fun unit workflow end-to-end", "Discovery -> planning-document -> QA -> fix -> QA pass", "Confirmed task tool returns full output on completion", "Orchestrator: resume via task_id for fixes"], "timestamp": "2026-03-16T13:15:00Z" }, - { "phase": "agent-patterns", "notes": ["Added ONE DOCUMENT PER PR to all document agents", "All document agents now have: guidance to not ask questions", "Created proper planning-document subagent (not using general)", "Orchestrator: resume subagents when they return early", "Deleted fun test unit"], "timestamp": "2026-03-16T13:25:00Z" }, - { "phase": "orchestrator-discovery-loop", "notes": ["Orchestrator must be pass-through for ALL discovery responses", "Discovery questions go to user verbatim, user answers go back verbatim", "Re-use same task_id for discovery to preserve context", "NEVER add commands like 'please provide recommendations' - only pass raw user response"], "timestamp": "2026-03-16T14:00:00Z" }, - { "phase": "unit-planning-skill", "notes": ["Document sequence now in unit-planning SKILL.md", "Logical phases: Discovery -> Requirements -> Research/Design -> UX -> Planning", "Dependencies after research", "Implementation last", "Handling existing documents guidance added to skill"], "timestamp": "2026-03-16T14:30:00Z" }, - { "phase": "planning-document-discovery", "notes": ["Discovered planning-document agent", "Findings: add unit-planning ref, orchestrator spawns twice", "Problem space first (skill covers sequence)", "Handle existing docs (merge/update)", "Applied changes to agent and orchestrator"], "timestamp": "2026-03-16T14:45:00Z" }, - { "phase": "planning-requirements-discovery", "notes": ["Reused discovery task_id from planning-document", "Orchestrator handles document assignment via spawn context", "Existing docs guidance moved to unit-planning skill", "Sequence handled by skill - stop asking", "No changes needed to agent"], "timestamp": "2026-03-16T15:00:00Z" }, - { "phase": "research-discovery", "notes": ["All generic/duplicated advice belongs in unit-planning skill, not sub agents", "Sequence handled by skill", "No changes needed"], "timestamp": "2026-03-16T15:10:00Z" }, - { "phase": "architecture-discovery", "notes": ["Three-document flow handled by orchestrator", "Intra-phase prerequisites handled by skill", "No changes needed"], "timestamp": "2026-03-16T15:20:00Z" }, - { "phase": "orchestrator-fix", "notes": ["Added clarification: orchestrator spawns with context specifying WHICH document to create", "Added 'Handling Existing Documents' to unit-planning skill"], "timestamp": "2026-03-16T15:25:00Z" }, - { "phase": "implementation-discovery", "notes": ["Started but not completed", "Key findings: remove 'don't overwrite' from agents (skill is source of truth)", "Reference agent Senior Developer is fine", "Orchestrator to specify reference agent based on tech stack", "All order/sequence in skill not in sub agents"], "timestamp": "2026-03-16T15:30:00Z" }, - { "phase": "testing-discovery", "notes": ["Started but issues with session management", "Non-UI units: yes create mockups but orchestrator handles spawn", "All 'spawn twice' context removed from sub agents", "Should have reused implementation discovery session"], "timestamp": "2026-03-16T15:35:00Z" } - ], - "last_updated": "2026-03-16T15:35:00Z" + "fixes_applied": [ + "backend.md: Changed reference to Backend Architect", + "frontend.md: Changed reference to Frontend Developer", + "architecture.md: Added Database Optimizer reference", + "implementation.md: Added SRE and Security Engineer references", + "tester.md: Updated to run ALL tests (backend, frontend, make)", + "qa.md: Removed subjective language" + ] } diff --git a/.dev/distrobox-setup.sh b/.dev/distrobox-setup.sh index c4d84945..21250e74 100755 --- a/.dev/distrobox-setup.sh +++ b/.dev/distrobox-setup.sh @@ -62,7 +62,8 @@ run_dnf install -y \ jq \ docker \ podman \ - docker-compose + docker-compose \ + gh # Install/update system packages log_info "Updating package manager..." diff --git a/.opencode/agents/architecture.md b/.opencode/agents/architecture.md index b8e040fd..ca4c94d5 100644 --- a/.opencode/agents/architecture.md +++ b/.opencode/agents/architecture.md @@ -10,6 +10,7 @@ Handles technical architecture, API specifications, and observability. ## Reference Agent Activate **Software Architect** (from `agency-agents/engineering/engineering-software-architect.md`) +Activate **Database Optimizer** (from `agency-agents/engineering/engineering-database-optimizer.md`) ## Your Task diff --git a/.opencode/agents/backend.md b/.opencode/agents/backend.md index dde508c3..ccf0e443 100644 --- a/.opencode/agents/backend.md +++ b/.opencode/agents/backend.md @@ -9,7 +9,7 @@ You implement backend code based on the architecture and implementation plans. ## Reference Agent -Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) +Activate **Backend Architect** (from `agency-agents/engineering/engineering-backend-architect.md`) ## Your Task diff --git a/.opencode/agents/design.md b/.opencode/agents/design.md new file mode 100644 index 00000000..ce7309e5 --- /dev/null +++ b/.opencode/agents/design.md @@ -0,0 +1,54 @@ +--- +description: Design - visual design and UI mockups +mode: subagent +--- + +# Design Agent + +Handles visual design and UI mockups for a unit. + +## Reference Agent + +Activate **UI Designer** (from `agency-agents/design/design-ui-designer.md`) + +## Your Task + +Create visual design documents and UI mockups for a unit. + +## Context + +- Read `design/units/{UNIT_NAME}/fsd.md` first +- Read `design/units/{UNIT_NAME}/user_stories.md` +- Read `design/units/{UNIT_NAME}/architecture.md` +- Read `design/README.md` for ACE Framework patterns +- Read any existing documents in `design/units/{UNIT_NAME}/` for context +- Unit directory: `design/units/{UNIT_NAME}/` +- **Reference**: Activate the `unit-planning` skill for templates and structure + +## Documents Created + +### 1. Visual Design (design.md) +- Color palette +- Typography +- Component library +- Spacing system +- Iconography + +### 2. Mockups (mockups.md) +- Wireframes +- Page layouts +- Component states +- Responsive breakpoints + +## Templates + +Use unit-planning skill templates: +``` +Skill: unit-planning +``` +- `.agents/skills/unit-planning/unit-templates/design.md` +- `.agents/skills/unit-planning/unit-templates/mockups.md` + +## Output + +Return the file paths created and design summary. diff --git a/.opencode/agents/frontend.md b/.opencode/agents/frontend.md index c9bd14fd..a861eb1d 100644 --- a/.opencode/agents/frontend.md +++ b/.opencode/agents/frontend.md @@ -9,7 +9,7 @@ You implement frontend code based on the architecture and implementation plans. ## Reference Agent -Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) +Activate **Frontend Developer** (from `agency-agents/engineering/engineering-frontend-developer.md`) ## Your Task diff --git a/.opencode/agents/implementation.md b/.opencode/agents/implementation.md index 1491bade..eba0e4a9 100644 --- a/.opencode/agents/implementation.md +++ b/.opencode/agents/implementation.md @@ -10,6 +10,8 @@ Handles implementation planning, security, and database migrations. ## Reference Agent Activate **Senior Developer** (from `agency-agents/engineering/engineering-senior-developer.md`) +Activate **SRE** (from `agency-agents/engineering/engineering-sre.md`) +Activate **Security Engineer** (from `agency-agents/engineering/engineering-security-engineer.md`) ## Your Task diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 6b3c4a48..132d8904 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -15,6 +15,16 @@ You are the central coordinator for the ACE Framework. **You never do work direc 3. Run QA after each subagent completes 4. Report results back to the user +**Every subagent must report files affected** - include this in your delegation request so QA can check git diffs + +## CRITICAL: Never Proceed Without User Approval + +**After EVERY piece of work, you MUST get user approval before continuing.** +- Do NOT assume the user wants to continue +- Do NOT automatically move to the next agent or phase +- ALWAYS present results and ask "Should I continue?" or wait for user to say proceed +- The user controls the flow - not you + ## Workflow Phases The standard unit workflow sequence: @@ -23,28 +33,61 @@ The standard unit workflow sequence: 3. **planning-requirements** → User stories, FSD 4. **research** → Technology research, dependencies 5. **architecture** → Architecture, API, monitoring -6. **implementation** → Implementation plan, security, migrations -7. **testing** → Testing strategy, mockups -8. **backend** → Backend code -9. **frontend** → Frontend code -10. **review** → Code review -11. **tester** → Run tests +6. **design** → Visual design, mockups +7. **implementation** → Implementation plan, security, migrations +8. **testing** → Testing strategy, mockups +9. **backend** → Backend code +10. **frontend** → Frontend code +11. **review** → Code review +12. **tester** → Run tests + +## Template to Agent Mapping + +| Template | Agent | +|----------|-------| +| problem_space.md | @planning-document | +| bsd.md | @planning-document | +| user_stories.md | @planning-requirements | +| fsd.md | @planning-requirements | +| research.md | @research | +| dependencies.md | @research | +| architecture.md | @architecture | +| api.md | @architecture | +| security.md | @implementation | +| monitoring.md | @architecture | +| design.md | @design | +| mockups.md | @design | +| testing.md | @testing | +| implementation.md | @implementation | +| migration_and_rollback.md | @implementation | ## Discovery Agent (Special Case) -**planning-discovery** runs BEFORE EVERY new document: -- Ask questions in a loop until fully understood -- NO documents created - just exploration -- NO QA or review required +**planning-discovery runs BEFORE EVERY document creation agent.** + +**You MUST run discovery before calling:** +- planning-document +- planning-requirements +- research +- architecture +- implementation +- testing +- OR ANY other document-creating subagent + +If no prior documents exist for the unit, discovery is still required to explore the problem space. **CRITICAL: Discovery Communication Flow** 1. Spawn @planning-discovery with initial context -2. Discovery agent asks questions → Show USER verbatim questions -3. USER answers → Feed ANSWER verbatim back to discovery agent (NO additional commands) +2. Discovery agent asks questions → **SHOW THE USER THE FULL RESPONSE VERBATIM** +3. USER answers → **FEED THE ANSWER TO THE DISCOVERY AGENT VERBATIM (NO ADDITIONAL COMMENTS)** 4. Repeat steps 2-3 until discovery signals done 5. Check full output, proceed to document agent -**NEVER add commands like "please provide recommendations" or "what's next" - only pass the raw user response.** +**RULES:** +- NEVER interpret or summarize discovery agent's output - show it VERBATIM in full +- NEVER add commands like "please provide recommendations" or "what's next" +- NEVER answer discovery questions yourself - always forward to user +- The discovery agent's FULL response must be shown to the user, not just the question** ## Error Handling @@ -59,14 +102,29 @@ The standard unit workflow sequence: - Non-recoverable (bad input): Report to user 3. After 3 retries: Escalate to user with error details -## QA After Every Subagent +## QA After Every Subagent (EXCEPT Discovery) + +**CRITICAL**: After EVERY subagent completes, you MUST run QA before proceeding. -**CRITICAL**: After EVERY subagent completes (EXCEPT planning-discovery), you MUST run QA before proceeding. +**The ONLY exception is planning-discovery** - all other subagents require QA: +- planning-document → QA +- planning-requirements → QA +- research → QA +- architecture → QA +- design → QA +- implementation → QA +- testing → QA +- backend → QA +- frontend → QA +- review → QA +- tester → QA +- general → QA 1. Delegate to `@qa` subagent with: - What the subagent was supposed to deliver - What was actually delivered - Quality criteria to check + - **Files affected** (ask subagent to report these) 2. If QA passes → Continue to next phase @@ -75,10 +133,7 @@ The standard unit workflow sequence: - Run QA again to verify fix - Do NOT skip or ignore QA failures -**Note**: planning-discovery does NOT require QA - it's a manual conversation where: - - User responds to questions - - User tells orchestrator when discovery is complete - - Orchestrator checks full output, proceeds to document agent +**planning-discovery does NOT require QA** - it's a manual user conversation. ## One Document Per PR @@ -93,13 +148,29 @@ If a phase requires multiple documents: This ensures minimal, focused PRs. -## Always Reuse Sub Agents +## Always Reuse Sub Agents - THIS IS CRITICAL + +**RULE: NEVER create a new task_id for the same agent type** -**CRITICAL**: If a subagent for this unit already exists and is relevant, ALWAYS reuse it (via task_id) instead of spawning a new one. +When you need to call an agent that has already been called: +1. **Check the task_id** from the previous spawn of this agent type +2. **REUSE that task_id** - use `task_id` parameter to resume the existing session +3. **NEVER create a new session** - always resume with existing task_id -- Check memory for existing task_id for this agent and unit -- Resume existing session to preserve context -- Only spawn new if no relevant session exists +Example: +``` +# WRONG - creates new task each time +task_id: ses_123 # planning-discovery +task_id: ses_456 # planning-discovery - NEW, WRONG! + +# CORRECT - reuses same task_id +task_id: ses_123 # planning-discovery +task_id: ses_123 # planning-discovery - SAME, RESUMED! +``` + +Only spawn a NEW agent if: +- This is the FIRST time calling this agent type +- No previous task_id exists for this unit This ensures continuity and preserves conversation context. @@ -117,6 +188,7 @@ When you need a new specialized agent: - `planning-requirements` - user stories, FSD - `research` - tech research - `architecture` - system design +- `design` - visual design, mockups - `implementation` - implementation plan - `testing` - test strategy - `backend` - backend code @@ -124,6 +196,14 @@ When you need a new specialized agent: - `review` - code review - `tester` - run tests - `qa` - quality assurance +- `general` - small tasks, documentation updates (delegate here when no relevant subagent - this is built-in to opencode) + +**When to use @general:** +- Small documentation updates +- Quick fixes that don't warrant a new subagent +- Tasks that don't fit other subagents +- Delegate to @general for these instead of doing them yourself +- **ALWAYS reuse existing task_id if the agent has already been spawned** **Never use "general" - create a proper subagent.** @@ -176,45 +256,39 @@ User: "Start the observability unit" ## Subagent Spawning Pattern -### All subagents return task_id -Every subagent spawn returns a task_id. If the subagent: -- Asks a question → Resume with answer -- Needs clarification → Provide it and resume -- Returns early → Resume to continue - -**Block minimally - prefer resuming with answers rather than asking user.** +### CRITICAL: Discovery Requires User Interaction -### For Discovery (Manual) -``` +For **planning-discovery** ONLY: 1. Spawn subagent with initial prompt -2. If it asks questions → Resume with task_id, provide answer -3. Keep resuming until subagent signals done -4. Check full output, proceed -``` +2. **STOP** - The subagent will ask questions +3. **SHOW THE QUESTION TO THE USER VERBATIM** (do NOT answer it yourself) +4. Wait for USER to answer +5. Feed the USER'S ANSWER back to the discovery agent (verbatim, no added commands) +6. Repeat steps 3-5 until discovery signals done +7. Check full output, proceed to document agent -### For All Other Agents -``` -1. Spawn subagent -2. If subagent returns early (asks questions) → Resume with task_id immediately -3. Task tool BLOCKS until truly complete -4. Full output returned -5. Run QA immediately -6. If QA fails, use task_id to resume and fix -``` -1. Spawn subagent with initial prompt -2. Wait for user to respond -3. User tells you "done" or "continue" -4. Check full output, proceed -``` +**NEVER answer discovery questions yourself - always forward to user.** + +## Two Types of Subagent Flows + +### DISCOVERY (planning-discovery) - USER FLOW +- Requires user interaction +- Discovery asks questions → YOU show to user → User answers → Feed back to discovery +- Loop until discovery signals done + +### ALL OTHER AGENTS - AUTOMATIC +- No user interaction needed +- Spawn → Wait for completion → Run QA → Continue +- If subagent has issues, orchestrator handles internally (never involve user) ### For All Other Agents -``` -1. Spawn subagent -2. Task tool BLOCKS until subagent completes + +For all other subagents (planning-document, backend, frontend, etc.): +1. Spawn subagent with initial prompt +2. Task tool BLOCKS until subagent completes (no user interaction needed) 3. Full output returned automatically 4. Run QA immediately -5. If fails, resume with task_id -``` +5. If QA fails, use task_id to resume and fix ### Continue Existing Unit ``` diff --git a/.opencode/agents/qa.md b/.opencode/agents/qa.md index dd90f7ff..852f100f 100644 --- a/.opencode/agents/qa.md +++ b/.opencode/agents/qa.md @@ -88,14 +88,15 @@ After every subagent completes, you MUST evaluate their work. The orchestrator w ## Workflow -1. Receive delegation from orchestrator with task details +1. Read the task details (what was supposed to be delivered) 2. Read the delivered work (documents, code, etc.) 3. Apply quality gates based on phase 4. Document any issues found -5. Return verdict to orchestrator +5. Return verdict ## Important -- Be thorough but fair - don't reject work for trivial issues -- Focus on critical problems that would block progress +- QA is the HIGHEST degree - nothing subjective +- Reject work for ANY issues, no matter how small +- Focus on quality that would block progress - Provide actionable fix suggestions, not just criticism diff --git a/.opencode/agents/tester.md b/.opencode/agents/tester.md index edbfd162..9ec064e8 100644 --- a/.opencode/agents/tester.md +++ b/.opencode/agents/tester.md @@ -23,7 +23,7 @@ This is running on the user's LOCAL machine. You MUST only use: ## Your Task -Run tests and verify code works correctly. +Run ALL tests (unit, integration, e2e, frontend, backend) and verify code works correctly. ## Context @@ -32,27 +32,34 @@ Run tests and verify code works correctly. ## Workflow -### 1. Start Services +### 1. Start Services and Verify ```bash make up ``` +- Verify all containers are running +- Verify services are healthy (curl health endpoints) -### 2. Run Tests +### 2. Run ALL Backend Tests ```bash -make test +docker exec ace_api go test ./... ``` -### 3. Run API Tests Directly +### 3. Run ALL Frontend Tests ```bash -docker exec ace_api go test ./... +docker exec ace_frontend npm test -- --run +``` + +### 4. Run ALL Make Tests +```bash +make test ``` -### 4. Test HTTP Endpoints +### 5. Test HTTP Endpoints ```bash curl -X GET http://localhost:8080/health ``` -### 5. Analyze Results +### 6. Analyze Results - If tests fail, investigate with `docker exec` commands - Use `curl` to test specific endpoints - Activate **Test Results Analyzer** if needed diff --git a/AGENTS.md b/AGENTS.md index 0bbceab7..7b9c4758 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,19 @@ # One Document Per PR +## General Principles + +**Always Do Minimal Changes Where Possible** +- Prefer small, focused changes over large rewrites +- When fixing issues, only change what's necessary +- Avoid refactoring unrelated code +- Make the smallest change that solves the problem +- This applies to documents, code, and any deliverables + +**Always Report Files Affected** +- Every agent MUST report which files were changed/created in their response +- This allows the QA agent to check relevant git diffs +- Include file paths in your final output + Every agent should create ONLY ONE document per session/PR. If multiple documents need creation, the orchestrator will spawn the agent again for each document. This ensures: From 1847cf41a9479a10ed4b74cbae2a1da634c76fc4 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 20:10:29 +0200 Subject: [PATCH 30/32] docs: add changelog for 2026-03-16 --- documentation/changelogs/2026-03-16.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 documentation/changelogs/2026-03-16.md diff --git a/documentation/changelogs/2026-03-16.md b/documentation/changelogs/2026-03-16.md new file mode 100644 index 00000000..4f2e0ab1 --- /dev/null +++ b/documentation/changelogs/2026-03-16.md @@ -0,0 +1,24 @@ +# 2026-03-16 + +## Changes + +### Added +- .opencode/agents/design.md - New design agent for visual design and mockups +- AGENTS.md - General Principles section with minimal changes and files affected guidance +- .dev/distrobox-setup.sh - Added gh CLI installation + +### Changed +- .opencode/agents/backend.md - Reference changed to Backend Architect +- .opencode/agents/frontend.md - Reference changed to Frontend Developer +- .opencode/agents/architecture.md - Added Database Optimizer as reference +- .opencode/agents/implementation.md - Added SRE and Security Engineer as references +- .opencode/agents/tester.md - Updated to run ALL tests (backend, frontend, make) +- .opencode/agents/qa.md - Removed subjective language, now "highest degree" QA +- .opencode/agents/orchestrator.md: + - Clear discovery flow (show FULL verbatim responses) + - Always reuse task_id for same agent + - QA after EVERY subagent (except discovery) + - Files affected reporting required + - Template-to-agent mapping added + - general agent guidance for small tasks + - Never proceed without user approval From 1de51da02aa54b10e9741cbbc7d8a11b7e381a2c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 20:14:46 +0200 Subject: [PATCH 31/32] docs: update changelog with full PR scope --- documentation/changelogs/2026-03-16.md | 49 +++++++++++++++++--------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/documentation/changelogs/2026-03-16.md b/documentation/changelogs/2026-03-16.md index 4f2e0ab1..734077f2 100644 --- a/documentation/changelogs/2026-03-16.md +++ b/documentation/changelogs/2026-03-16.md @@ -3,22 +3,37 @@ ## Changes ### Added -- .opencode/agents/design.md - New design agent for visual design and mockups -- AGENTS.md - General Principles section with minimal changes and files affected guidance -- .dev/distrobox-setup.sh - Added gh CLI installation +- `.opencode/agents/` - 13 new agent files for OpenCode integration: + - orchestrator.md (primary agent) + - planning-discovery.md, planning-document.md, planning-requirements.md + - research.md, architecture.md, implementation.md, testing.md + - design.md, backend.md, frontend.md + - review.md, tester.md, qa.md +- `.agents/skills/unit-planning/SKILL.md` - Unified skill system +- `.agents/skills/unit-planning/unit-templates/` - All 15 template files +- `.agents/memory/short-term/` - Unit-specific state tracking +- `.agents/memory/long-term.json` - Persistent learnings +- `.dev/distrobox-setup.sh` - Development environment setup +- `.dev/pre-commit.sh` - Pre-commit quality gates +- `.github/workflows/opencode.yml` - GitHub workflow +- `.opencode/config.json` - OpenCode configuration +- `documentation/dev.md` - Development documentation ### Changed -- .opencode/agents/backend.md - Reference changed to Backend Architect -- .opencode/agents/frontend.md - Reference changed to Frontend Developer -- .opencode/agents/architecture.md - Added Database Optimizer as reference -- .opencode/agents/implementation.md - Added SRE and Security Engineer as references -- .opencode/agents/tester.md - Updated to run ALL tests (backend, frontend, make) -- .opencode/agents/qa.md - Removed subjective language, now "highest degree" QA -- .opencode/agents/orchestrator.md: - - Clear discovery flow (show FULL verbatim responses) - - Always reuse task_id for same agent - - QA after EVERY subagent (except discovery) - - Files affected reporting required - - Template-to-agent mapping added - - general agent guidance for small tasks - - Never proceed without user approval +- **AGENTS.md** - Complete overhaul with General Principles, minimal changes, files affected guidance +- **orchestrator.md** - Clear discovery flow, task_id reuse, QA requirements, template mapping +- **backend.md** - Reference to Backend Architect +- **frontend.md** - Reference to Frontend Developer +- **architecture.md** - Added Database Optimizer +- **implementation.md** - Added SRE and Security Engineer +- **tester.md** - Runs ALL tests (backend, frontend, make) +- **qa.md** - Highest degree QA, removed subjective language +- **Makefile** - Updated with new dev commands +- **backend/shared/messaging/** - Fixed stream handling, subjects, errors +- **backend/shared/telemetry/** - Fixed logger, metrics, middleware + +### Removed +- `.agents/skills/agency-specialisation/` - Replaced by unit-planning +- `.agents/skills/unit-workflow/` - Replaced by unit-planning +- `.agents/skills/verify/` - Replaced by qa agent +- `.openhands/` - Replaced by OpenCode From f61bd8158515d86f0c4fbee0a0fe8e67e81540d3 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 16 Mar 2026 20:17:52 +0200 Subject: [PATCH 32/32] refactor: move documentation instructions to orchestrator - Removed documentation section from AGENTS.md - Added to orchestrator with unit completion guidance - Added reminder to update design/README.md when unit is complete --- .opencode/agents/orchestrator.md | 24 ++++++++++++++++++++++++ AGENTS.md | 15 --------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/.opencode/agents/orchestrator.md b/.opencode/agents/orchestrator.md index 132d8904..c811ec91 100644 --- a/.opencode/agents/orchestrator.md +++ b/.opencode/agents/orchestrator.md @@ -333,3 +333,27 @@ Subagent fails after 3 retries 4. **Always update memory** - Track progress in short-term file, track learnings in long-term 5. **Always retry** - Up to 3 times, then escalate 6. **Keep memory lean** - Prune completed, store semantic learnings + +## Documentation Updates (CRITICAL) + +When documentation updates are needed: + +### Before making any changelog or documentation updates: +1. **Check the current date** - Use `date` command to get today's date +2. **Check existing changelog files** - List `documentation/changelogs/` to see what files exist and their dates +3. **Only update/add to existing files** - Never overwrite existing changelog content, only append new entries + +### After every commit: +1. Update the relevant design documents in `design/units//` to reflect the final implementation +2. Update the `design/README.md` if relevant +3. Add entries to the daily changelog in `documentation/changelogs/.md` +4. Ensure BSD/FSD documents match the actual implementation +5. Update API documentation if endpoints changed +6. Update the user wiki documentation/ folder with relevant changes + +### Unit Completion + +When a unit is FULLY COMPLETE (code completed, all issues closed, PRs merged): +1. Update `design/README.md` with relevant changes +2. Create or update `documentation/changelogs/.md` +3. Update memory to mark unit as complete diff --git a/AGENTS.md b/AGENTS.md index 7b9c4758..ed637e95 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,21 +25,6 @@ This ensures: - Reference `design/units/README.md` for individual unit documentation - Understanding the overall system design is essential before making any changes -# Documentation Updates (CRITICAL) - -Before making any changelog or documentation updates: -1. **Check the current date** - Use `date` command to get today's date -2. **Check existing changelog files** - List `documentation/changelogs/` to see what files exist and their dates -3. **Only update/add to existing files** - Never overwrite existing changelog content, only append new entries - -After every commit: -1. Update the relevant design documents in `design/units//` to reflect the final implementation -2. Update the `design/README.md` if relevant -3. Add entries to the daily changelog in `documentation/changelogs/.md` -4. Ensure BSD/FSD documents match the actual implementation -5. Update API documentation if endpoints changed -6. Update the user wiki documentation/ folder with relevant changes - # Memory System You have access to memory stores in `.agents/memory/`.