diff --git a/.agents/skills/speckit-plan/SKILL.md b/.agents/skills/speckit-plan/SKILL.md index c4be84923..b761b014b 100644 --- a/.agents/skills/speckit-plan/SKILL.md +++ b/.agents/skills/speckit-plan/SKILL.md @@ -137,9 +137,9 @@ You **MUST** consider the user input before proceeding (if not empty). - Skip if project is purely internal (build scripts, one-off tools, etc.) 3. **Agent context update**: - - Update the plan reference between the `` and `` markers in `AGENTS.md` to point to the plan file created in step 1 (the IMPL_PLAN path) + - Do not copy plan-derived context into `AGENTS.md` or agent-specific instruction files. Repository instructions are intentionally feature-neutral; feature context remains in the plan artifacts. -**Output**: data-model.md, /contracts/*, quickstart.md, updated agent context file +**Output**: data-model.md, /contracts/*, quickstart.md ## Key rules diff --git a/.claude/skills/speckit-plan/SKILL.md b/.claude/skills/speckit-plan/SKILL.md index a2f723c06..e272afe71 100644 --- a/.claude/skills/speckit-plan/SKILL.md +++ b/.claude/skills/speckit-plan/SKILL.md @@ -138,13 +138,9 @@ You **MUST** consider the user input before proceeding (if not empty). - Skip if project is purely internal (build scripts, one-off tools, etc.) 3. **Agent context update**: - - Run `.specify/scripts/bash/update-agent-context.sh claude` - - These scripts detect which AI agent is in use - - Update the appropriate agent-specific context file - - Add only new technology from current plan - - Preserve manual additions between markers + - Do not run the legacy plan-to-agent-context updater. Repository instructions are intentionally feature-neutral; keep feature context in the plan artifacts. -**Output**: data-model.md, /contracts/*, quickstart.md, agent-specific file +**Output**: data-model.md, /contracts/*, quickstart.md ## Key rules diff --git a/.github/agents/copilot-instructions.md b/.github/agents/copilot-instructions.md index e410cb1f5..b2a55b112 100644 --- a/.github/agents/copilot-instructions.md +++ b/.github/agents/copilot-instructions.md @@ -1,29 +1,3 @@ -# main Development Guidelines +# Elsa Core Agent Instructions -Auto-generated from all feature plans. Last updated: 2026-03-08 - -## Active Technologies - -- C# latest on .NET 10.0 primary, with existing multi-target support for .NET 8.0 and .NET 9.0 + FastEndpoints, Elsa.Api.Common abstractions, CShells, CShells.FastEndpoints.Abstractions, Refit client contracts, xUnit component test infrastructure (001-shell-reload-api) - -## Project Structure - -```text -src/ -tests/ -``` - -## Commands - -# Add commands for C# latest on .NET 10.0 primary, with existing multi-target support for .NET 8.0 and .NET 9.0 - -## Code Style - -C# latest on .NET 10.0 primary, with existing multi-target support for .NET 8.0 and .NET 9.0: Follow standard conventions - -## Recent Changes - -- 001-shell-reload-api: Added C# latest on .NET 10.0 primary, with existing multi-target support for .NET 8.0 and .NET 9.0 + FastEndpoints, Elsa.Api.Common abstractions, CShells, CShells.FastEndpoints.Abstractions, Refit client contracts, xUnit component test infrastructure - - - +Use the canonical repository guidance in [AGENTS.md](../../AGENTS.md). Keep feature-specific plan details in `specs/`; they are not copied into this file. diff --git a/.github/agents/speckit.plan.agent.md b/.github/agents/speckit.plan.agent.md index 0ffb929d0..48ac6695f 100644 --- a/.github/agents/speckit.plan.agent.md +++ b/.github/agents/speckit.plan.agent.md @@ -76,13 +76,9 @@ You **MUST** consider the user input before proceeding (if not empty). - Skip if project is purely internal (build scripts, one-off tools, etc.) 3. **Agent context update**: - - Run `.specify/scripts/bash/update-agent-context.sh copilot` - - These scripts detect which AI agent is in use - - Update the appropriate agent-specific context file - - Add only new technology from current plan - - Preserve manual additions between markers + - Do not copy plan-derived context into `AGENTS.md` or agent-specific instruction files. The compatibility updater is intentionally disabled so repository instructions remain feature-neutral. -**Output**: data-model.md, /contracts/*, quickstart.md, agent-specific file +**Output**: data-model.md, /contracts/*, quickstart.md ## Key rules diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2cb307856..6003fd0f1 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,264 +1,3 @@ -# Copilot Coding Agent Instructions for Elsa Workflows +# Elsa Core Coding Agent Instructions -## Repository Overview - -**Elsa Workflows** is a powerful .NET workflow library that enables workflow execution within any .NET application. This is version 3.0, supporting .NET 8.0, .NET 9.0 and .NET 10.0 and providing both a visual designer (from a different repository, elsa-studio) and programmatic workflow definition capabilities. - -### Key Statistics -- **Language**: C# (.NET 10.0) -- **Architecture**: Modular library with 104+ projects -- **Code Size**: ~3,500 C# files across modules -- **License**: MIT -- **Build System**: NUKE build automation -- **Target Frameworks**: .NET 10.0 (primary) - -## High-Level Architecture - -### Directory Structure -``` -src/ -├── apps/ # Reference applications (5 projects) -│ ├── Elsa.Server.Web # Workflow server only -│ └── Elsa.Server.LoadBalancer # Load balancer -├── common/ # Shared libraries (8 projects) -├── modules/ # Core functionality modules (70+ projects) -│ ├── Elsa.Workflows.Core # Core workflow engine -│ ├── Elsa.Workflows.Runtime # Runtime execution -│ ├── Elsa.Workflows.Api # REST API -│ ├── Elsa.Http # HTTP activities -│ ├── Elsa.Email # Email activities -│ └── [many others] # Database, messaging, etc. -└── clients/ # API clients -test/ -├── unit/ # Unit tests -├── integration/ # Integration tests -├── component/ # Component tests -└── performance/ # Performance tests -build/ # NUKE build configuration -docker/ # Docker configurations -``` - -### Core Components -- **Elsa.Workflows.Core**: Main workflow engine and activities -- **Elsa.Workflows.Runtime**: Workflow execution runtime -- **Elsa.Workflows.Api**: RESTful API for workflow management -- **Elsa.Workflows.Management**: Workflow definition management -- **Elsa modules**: Specialized functionality (HTTP, persistence, scheduling, etc.) - -## Build Instructions - -### Prerequisites -- **.NET 10.0 SDK** -- **Build time**: Initial restore ~1-2 minutes, full compile ~5-10 minutes - -### Build Commands - -**Primary build script**: `./build.sh` (Linux/macOS) or `.\build.cmd` (Windows) - -```bash -# View available targets -./build.sh --help - -# Clean build artifacts -./build.sh Clean - -# Restore packages (may show warnings for inaccessible feeds) -./build.sh Restore --ignore-failed-sources - -# Compile core components (excludes studio apps) -./build.sh Compile - -# Run tests (limited due to external dependencies) -./build.sh Test - -# Create NuGet packages -./build.sh Pack - -# Full CI pipeline (compile, test, pack) -./build.sh Compile Test Pack -``` - -**Direct dotnet commands** for core components: -```bash -# Build specific core projects that don't require external packages -dotnet restore src/modules/Elsa.Workflows.Core/ --ignore-failed-sources -dotnet build src/modules/Elsa.Workflows.Core/ --no-restore -dotnet restore src/modules/Elsa.Workflows.Runtime/ --ignore-failed-sources -dotnet build src/modules/Elsa.Workflows.Runtime/ --no-restore - -# Note: Server apps may fail due to WebhooksCore dependency -# Build and test individual core modules -find test/unit -name "*.csproj" | head -5 | xargs -I {} dotnet build {} -``` - -### Expected Build Warnings -- `NU1900`: Unable to load service index for external feeds (safe to ignore) -- `NU1801`: Service index warnings for feedz.io sources (safe to ignore) - -### Successful Build Indicators -- Core modules (Elsa.Workflows.Core, etc.) compile successfully -- Server applications (Elsa.Server.Web) build -- Most modules show "succeeded with X warning(s)" (warnings are acceptable) - -## Testing - -### Test Structure -- **Unit tests**: `test/unit/` - Fast, isolated tests -- **Integration tests**: `test/integration/` - End-to-end scenarios -- **Component tests**: `test/component/` - Feature testing -- **Performance tests**: `test/performance/` - Benchmarks - -### Running Tests -```bash -# Via NUKE build system -./build.sh Test - -# Direct dotnet test (for accessible projects) -dotnet test test/unit/[specific-project]/ -dotnet test --no-build --no-restore [project-path] -``` - -**Note**: Many tests may fail to run due to external package dependencies. Focus on core workflow engine tests that don't require studio packages. - -## Development Guidelines - -### Code Standards -- **Language version**: C# latest -- **Target framework**: .NET 10.0 -- **Nullable reference types**: Enabled -- **Implicit usings**: Enabled -- **EditorConfig**: Configured (4-space indentation, CRLF line endings) - -### Architecture Patterns -- **Modular design**: Each feature area is a separate project/module -- **Dependency injection**: Heavy use of Microsoft.Extensions.DependencyInjection -- **Activity-based**: Workflows are built from composable activities -- **Async/await**: Extensive use throughout for scalability - -### Common Gotchas -1. **NuGet Source Mapping**: Configured in NuGet.Config, restricts where packages can be sourced -2**Multiple Target Frameworks**: Some projects conditionally target different frameworks -3**Build Warnings**: Many NU1900/NU1801 warnings are expected and safe - -## Continuous Integration - -### GitHub Actions Workflow -- **Trigger**: Pull requests to `main` branch -- **Runner**: ubuntu-latest -- **.NET Version**: 10.x (latest) -- **Commands**: `./build.cmd Compile Test Pack` -- **File**: `.github/workflows/pr.yml` (auto-generated by NUKE) - -### CI Pipeline Steps -1. Checkout code -2. Setup .NET 10.x SDK -3. Execute: Compile → Test → Pack -4. Expected warnings for external feed access -5. Studio apps may be excluded from CI builds - -## Key Configuration Files - -- **Build**: `build/Build.cs` (NUKE build configuration) -- **Dependencies**: `Directory.Packages.props` (central package management) -- **Global settings**: `Directory.Build.props` -- **NuGet**: `NuGet.Config` (package sources and mapping) -- **Solution**: `Elsa.sln` (119 projects) -- **Docker**: `docker/` directory with multiple Dockerfiles -- **GitHub Actions**: `.github/workflows/` (auto-generated) - -## Docker Support - -Multiple Docker configurations available: -- `ElsaServer.Dockerfile` - Server only -- `ElsaServerAndStudio.Dockerfile` - Combined server + studio -- `ElsaStudio.Dockerfile` - Studio only -- Docker Compose configurations for development - -## Quick Start for Development - -1. **Clone and build core components**: - ```bash - git clone [repo-url] - cd elsa-core - ./build.sh Clean Restore --ignore-failed-sources - ``` - -2. **Work with core modules** (avoid studio dependencies): - ```bash - cd src/modules/Elsa.Workflows.Core - dotnet build - dotnet test ../../test/unit/[related-tests]/ - ``` - -3. **Work with core modules that don't require external dependencies**: - ```bash - cd src/modules/Elsa.Workflows.Core - dotnet restore --ignore-failed-sources - dotnet build --no-restore - ``` - -## Running the Applications - -### Development Workflow Server - -To run the workflow server for development: - -```bash -cd src/apps/Elsa.Server.Web -dotnet restore --ignore-failed-sources -dotnet run -``` - -The server will start on the configured ports (check `appsettings.json` or environment variables). - -## Troubleshooting - -### Common Issues - -1. **Missing External Packages**: If you encounter `NU1101` errors for Elsa.Studio packages: - - This is expected for studio-related apps - - Focus development on core workflow modules instead - - Or use Docker images that have pre-built studio components - -2. **Build Fails on Server Apps**: If `Elsa.Server.Web` fails due to WebhooksCore: - - This is a known issue with external package feeds - - Try building individual core modules instead - - Use `--ignore-failed-sources` flag consistently - -3. **Test Failures**: If many tests fail to run: - - External package dependencies may be unavailable - - Run tests for specific core modules individually - - Focus on tests that don't require studio packages - -4. **Slow Initial Build**: First restore and compile can take 5-10+ minutes: - - This is normal for a large solution with 100+ projects - - Subsequent builds are much faster (incremental) - - Consider building specific projects/modules when iterating - -## Additional Resources - -### Documentation -- **Official Documentation**: [https://docs.elsaworkflows.io/](https://docs.elsaworkflows.io/) -- **README**: See [README.md](../README.md) for quick start and features overview -- **Contributing Guide**: See [CONTRIBUTING.md](../CONTRIBUTING.md) for contribution guidelines - -### Community Support -- **GitHub Issues**: [Report bugs and request features](https://github.com/elsa-workflows/elsa-core/issues) -- **GitHub Discussions**: [Ask questions and discuss](https://github.com/elsa-workflows/elsa-core/discussions) -- **Discord**: [Join the community chat](https://discord.gg/hhChk5H472) -- **Stack Overflow**: [Tag: elsa-workflows](http://stackoverflow.com/questions/tagged/elsa-workflows) - -### Enterprise Support -- **ELSA-X**: [Professional support and enterprise solutions](https://elsa-x.io) - -## Important Notes for Coding Agents - -1. **Always use `--ignore-failed-sources`** when restoring packages -2. **Focus on core workflow functionality** -3. **Build warnings are normal** - don't try to fix NU1900/NU1801 warnings -4. **Test individual modules** rather than solution-wide tests when external deps fail -5. **Use direct dotnet commands** for building specific components when NUKE fails -6. **Check project references** before attempting builds - some projects have conditional references -7. **Start with core modules** like `Elsa.Workflows.Core`, `Elsa.Workflows.Runtime` which are more likely to build successfully - -Trust these instructions for build and development workflows. Only search for additional information if these instructions are incomplete or found to be incorrect. \ No newline at end of file +Use the canonical repository guidance in [AGENTS.md](../AGENTS.md). It defines the supported layout, commands, conventions, and testing guidance. Keep feature-specific plan details in `specs/`; they are not copied into this file. diff --git a/.specify/scripts/bash/update-agent-context.sh b/.specify/scripts/bash/update-agent-context.sh index fdebac65f..5fdea8f5f 100755 --- a/.specify/scripts/bash/update-agent-context.sh +++ b/.specify/scripts/bash/update-agent-context.sh @@ -1,829 +1,9 @@ #!/usr/bin/env bash -# Update agent context files with information from plan.md -# -# This script maintains AI agent context files by parsing feature specifications -# and updating agent-specific configuration files with project information. -# -# MAIN FUNCTIONS: -# 1. Environment Validation -# - Verifies git repository structure and branch information -# - Checks for required plan.md files and templates -# - Validates file permissions and accessibility -# -# 2. Plan Data Extraction -# - Parses plan.md files to extract project metadata -# - Identifies language/version, frameworks, databases, and project types -# - Handles missing or incomplete specification data gracefully -# -# 3. Agent File Management -# - Creates new agent context files from templates when needed -# - Updates existing agent files with new project information -# - Preserves manual additions and custom configurations -# - Supports multiple AI agent formats and directory structures -# -# 4. Content Generation -# - Generates language-specific build/test commands -# - Creates appropriate project directory structures -# - Updates technology stacks and recent changes sections -# - Maintains consistent formatting and timestamps -# -# 5. Multi-Agent Support -# - Handles agent-specific file paths and naming conventions -# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Kiro CLI, or Antigravity -# - Can update single agents or all existing agent files -# - Creates default Claude file if no agent files exist -# -# Usage: ./update-agent-context.sh [agent_type] -# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli -# Leave empty to update all existing agent files +# Retained as a Speckit compatibility entry point. Plan-derived agent context +# is intentionally disabled so feature plans cannot rewrite repository-wide +# instructions with stale technology or historical-change summaries. -set -e +set -euo pipefail -# Enable strict error handling -set -u -set -o pipefail - -#============================================================================== -# Configuration and Global Variables -#============================================================================== - -# Get script directory and load common functions -SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/common.sh" - -# Get all paths and variables from common functions -eval $(get_feature_paths) - -NEW_PLAN="$IMPL_PLAN" # Alias for compatibility with existing code -AGENT_TYPE="${1:-}" - -# Agent-specific file paths -CLAUDE_FILE="$REPO_ROOT/CLAUDE.md" -GEMINI_FILE="$REPO_ROOT/GEMINI.md" -COPILOT_FILE="$REPO_ROOT/.github/agents/copilot-instructions.md" -CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc" -QWEN_FILE="$REPO_ROOT/QWEN.md" -AGENTS_FILE="$REPO_ROOT/AGENTS.md" -WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md" -KILOCODE_FILE="$REPO_ROOT/.kilocode/rules/specify-rules.md" -AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md" -ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md" -CODEBUDDY_FILE="$REPO_ROOT/CODEBUDDY.md" -QODER_FILE="$REPO_ROOT/QODER.md" -AMP_FILE="$REPO_ROOT/AGENTS.md" -SHAI_FILE="$REPO_ROOT/SHAI.md" -KIRO_FILE="$REPO_ROOT/AGENTS.md" -AGY_FILE="$REPO_ROOT/.agent/rules/specify-rules.md" -BOB_FILE="$REPO_ROOT/AGENTS.md" - -# Template file -TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md" - -# Global variables for parsed plan data -NEW_LANG="" -NEW_FRAMEWORK="" -NEW_DB="" -NEW_PROJECT_TYPE="" - -#============================================================================== -# Utility Functions -#============================================================================== - -log_info() { - echo "INFO: $1" -} - -log_success() { - echo "✓ $1" -} - -log_error() { - echo "ERROR: $1" >&2 -} - -log_warning() { - echo "WARNING: $1" >&2 -} - -# Cleanup function for temporary files -cleanup() { - local exit_code=$? - rm -f /tmp/agent_update_*_$$ - rm -f /tmp/manual_additions_$$ - exit $exit_code -} - -# Set up cleanup trap -trap cleanup EXIT INT TERM - -#============================================================================== -# Validation Functions -#============================================================================== - -validate_environment() { - # Check if we have a current branch/feature (git or non-git) - if [[ -z "$CURRENT_BRANCH" ]]; then - log_error "Unable to determine current feature" - if [[ "$HAS_GIT" == "true" ]]; then - log_info "Make sure you're on a feature branch" - else - log_info "Set SPECIFY_FEATURE environment variable or create a feature first" - fi - exit 1 - fi - - # Check if plan.md exists - if [[ ! -f "$NEW_PLAN" ]]; then - log_error "No plan.md found at $NEW_PLAN" - log_info "Make sure you're working on a feature with a corresponding spec directory" - if [[ "$HAS_GIT" != "true" ]]; then - log_info "Use: export SPECIFY_FEATURE=your-feature-name or create a new feature first" - fi - exit 1 - fi - - # Check if template exists (needed for new files) - if [[ ! -f "$TEMPLATE_FILE" ]]; then - log_warning "Template file not found at $TEMPLATE_FILE" - log_warning "Creating new agent files will fail" - fi -} - -#============================================================================== -# Plan Parsing Functions -#============================================================================== - -extract_plan_field() { - local field_pattern="$1" - local plan_file="$2" - - grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \ - head -1 | \ - sed "s|^\*\*${field_pattern}\*\*: ||" | \ - sed 's/^[ \t]*//;s/[ \t]*$//' | \ - grep -v "NEEDS CLARIFICATION" | \ - grep -v "^N/A$" || echo "" -} - -parse_plan_data() { - local plan_file="$1" - - if [[ ! -f "$plan_file" ]]; then - log_error "Plan file not found: $plan_file" - return 1 - fi - - if [[ ! -r "$plan_file" ]]; then - log_error "Plan file is not readable: $plan_file" - return 1 - fi - - log_info "Parsing plan data from $plan_file" - - NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file") - NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file") - NEW_DB=$(extract_plan_field "Storage" "$plan_file") - NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file") - - # Log what we found - if [[ -n "$NEW_LANG" ]]; then - log_info "Found language: $NEW_LANG" - else - log_warning "No language information found in plan" - fi - - if [[ -n "$NEW_FRAMEWORK" ]]; then - log_info "Found framework: $NEW_FRAMEWORK" - fi - - if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then - log_info "Found database: $NEW_DB" - fi - - if [[ -n "$NEW_PROJECT_TYPE" ]]; then - log_info "Found project type: $NEW_PROJECT_TYPE" - fi -} - -format_technology_stack() { - local lang="$1" - local framework="$2" - local parts=() - - # Add non-empty parts - [[ -n "$lang" && "$lang" != "NEEDS CLARIFICATION" ]] && parts+=("$lang") - [[ -n "$framework" && "$framework" != "NEEDS CLARIFICATION" && "$framework" != "N/A" ]] && parts+=("$framework") - - # Join with proper formatting - if [[ ${#parts[@]} -eq 0 ]]; then - echo "" - elif [[ ${#parts[@]} -eq 1 ]]; then - echo "${parts[0]}" - else - # Join multiple parts with " + " - local result="${parts[0]}" - for ((i=1; i<${#parts[@]}; i++)); do - result="$result + ${parts[i]}" - done - echo "$result" - fi -} - -#============================================================================== -# Template and Content Generation Functions -#============================================================================== - -get_project_structure() { - local project_type="$1" - - if [[ "$project_type" == *"web"* ]]; then - echo "backend/\\nfrontend/\\ntests/" - else - echo "src/\\ntests/" - fi -} - -get_commands_for_language() { - local lang="$1" - - case "$lang" in - *"Python"*) - echo "cd src && pytest && ruff check ." - ;; - *"Rust"*) - echo "cargo test && cargo clippy" - ;; - *"JavaScript"*|*"TypeScript"*) - echo "npm test \\&\\& npm run lint" - ;; - *) - echo "# Add commands for $lang" - ;; - esac -} - -get_language_conventions() { - local lang="$1" - echo "$lang: Follow standard conventions" -} - -create_new_agent_file() { - local target_file="$1" - local temp_file="$2" - local project_name="$3" - local current_date="$4" - - if [[ ! -f "$TEMPLATE_FILE" ]]; then - log_error "Template not found at $TEMPLATE_FILE" - return 1 - fi - - if [[ ! -r "$TEMPLATE_FILE" ]]; then - log_error "Template file is not readable: $TEMPLATE_FILE" - return 1 - fi - - log_info "Creating new agent context file from template..." - - if ! cp "$TEMPLATE_FILE" "$temp_file"; then - log_error "Failed to copy template file" - return 1 - fi - - # Replace template placeholders - local project_structure - project_structure=$(get_project_structure "$NEW_PROJECT_TYPE") - - local commands - commands=$(get_commands_for_language "$NEW_LANG") - - local language_conventions - language_conventions=$(get_language_conventions "$NEW_LANG") - - # Perform substitutions with error checking using safer approach - # Escape special characters for sed by using a different delimiter or escaping - local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g') - local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g') - local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g') - - # Build technology stack and recent change strings conditionally - local tech_stack - if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then - tech_stack="- $escaped_lang + $escaped_framework ($escaped_branch)" - elif [[ -n "$escaped_lang" ]]; then - tech_stack="- $escaped_lang ($escaped_branch)" - elif [[ -n "$escaped_framework" ]]; then - tech_stack="- $escaped_framework ($escaped_branch)" - else - tech_stack="- ($escaped_branch)" - fi - - local recent_change - if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then - recent_change="- $escaped_branch: Added $escaped_lang + $escaped_framework" - elif [[ -n "$escaped_lang" ]]; then - recent_change="- $escaped_branch: Added $escaped_lang" - elif [[ -n "$escaped_framework" ]]; then - recent_change="- $escaped_branch: Added $escaped_framework" - else - recent_change="- $escaped_branch: Added" - fi - - local substitutions=( - "s|\[PROJECT NAME\]|$project_name|" - "s|\[DATE\]|$current_date|" - "s|\[EXTRACTED FROM ALL PLAN.MD FILES\]|$tech_stack|" - "s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|g" - "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$commands|" - "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|" - "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|$recent_change|" - ) - - for substitution in "${substitutions[@]}"; do - if ! sed -i.bak -e "$substitution" "$temp_file"; then - log_error "Failed to perform substitution: $substitution" - rm -f "$temp_file" "$temp_file.bak" - return 1 - fi - done - - # Convert \n sequences to actual newlines - newline=$(printf '\n') - sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file" - - # Clean up backup files - rm -f "$temp_file.bak" "$temp_file.bak2" - - # Prepend Cursor frontmatter for .mdc files so rules are auto-included - if [[ "$target_file" == *.mdc ]]; then - local frontmatter_file - frontmatter_file=$(mktemp) || return 1 - printf '%s\n' "---" "description: Project Development Guidelines" "globs: [\"**/*\"]" "alwaysApply: true" "---" "" > "$frontmatter_file" - cat "$temp_file" >> "$frontmatter_file" - mv "$frontmatter_file" "$temp_file" - fi - - return 0 -} - - - - -update_existing_agent_file() { - local target_file="$1" - local current_date="$2" - - log_info "Updating existing agent context file..." - - # Use a single temporary file for atomic update - local temp_file - temp_file=$(mktemp) || { - log_error "Failed to create temporary file" - return 1 - } - - # Process the file in one pass - local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK") - local new_tech_entries=() - local new_change_entry="" - - # Prepare new technology entries - if [[ -n "$tech_stack" ]] && ! grep -q "$tech_stack" "$target_file"; then - new_tech_entries+=("- $tech_stack ($CURRENT_BRANCH)") - fi - - if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]] && ! grep -q "$NEW_DB" "$target_file"; then - new_tech_entries+=("- $NEW_DB ($CURRENT_BRANCH)") - fi - - # Prepare new change entry - if [[ -n "$tech_stack" ]]; then - new_change_entry="- $CURRENT_BRANCH: Added $tech_stack" - elif [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]]; then - new_change_entry="- $CURRENT_BRANCH: Added $NEW_DB" - fi - - # Check if sections exist in the file - local has_active_technologies=0 - local has_recent_changes=0 - - if grep -q "^## Active Technologies" "$target_file" 2>/dev/null; then - has_active_technologies=1 - fi - - if grep -q "^## Recent Changes" "$target_file" 2>/dev/null; then - has_recent_changes=1 - fi - - # Process file line by line - local in_tech_section=false - local in_changes_section=false - local tech_entries_added=false - local changes_entries_added=false - local existing_changes_count=0 - local file_ended=false - - while IFS= read -r line || [[ -n "$line" ]]; do - # Handle Active Technologies section - if [[ "$line" == "## Active Technologies" ]]; then - echo "$line" >> "$temp_file" - in_tech_section=true - continue - elif [[ $in_tech_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then - # Add new tech entries before closing the section - if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then - printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file" - tech_entries_added=true - fi - echo "$line" >> "$temp_file" - in_tech_section=false - continue - elif [[ $in_tech_section == true ]] && [[ -z "$line" ]]; then - # Add new tech entries before empty line in tech section - if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then - printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file" - tech_entries_added=true - fi - echo "$line" >> "$temp_file" - continue - fi - - # Handle Recent Changes section - if [[ "$line" == "## Recent Changes" ]]; then - echo "$line" >> "$temp_file" - # Add new change entry right after the heading - if [[ -n "$new_change_entry" ]]; then - echo "$new_change_entry" >> "$temp_file" - fi - in_changes_section=true - changes_entries_added=true - continue - elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then - echo "$line" >> "$temp_file" - in_changes_section=false - continue - elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then - # Keep only first 2 existing changes - if [[ $existing_changes_count -lt 2 ]]; then - echo "$line" >> "$temp_file" - ((existing_changes_count++)) - fi - continue - fi - - # Update timestamp - if [[ "$line" =~ \*\*Last\ updated\*\*:.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then - echo "$line" | sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/$current_date/" >> "$temp_file" - else - echo "$line" >> "$temp_file" - fi - done < "$target_file" - - # Post-loop check: if we're still in the Active Technologies section and haven't added new entries - if [[ $in_tech_section == true ]] && [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then - printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file" - tech_entries_added=true - fi - - # If sections don't exist, add them at the end of the file - if [[ $has_active_technologies -eq 0 ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then - echo "" >> "$temp_file" - echo "## Active Technologies" >> "$temp_file" - printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file" - tech_entries_added=true - fi - - if [[ $has_recent_changes -eq 0 ]] && [[ -n "$new_change_entry" ]]; then - echo "" >> "$temp_file" - echo "## Recent Changes" >> "$temp_file" - echo "$new_change_entry" >> "$temp_file" - changes_entries_added=true - fi - - # Ensure Cursor .mdc files have YAML frontmatter for auto-inclusion - if [[ "$target_file" == *.mdc ]]; then - if ! head -1 "$temp_file" | grep -q '^---'; then - local frontmatter_file - frontmatter_file=$(mktemp) || { rm -f "$temp_file"; return 1; } - printf '%s\n' "---" "description: Project Development Guidelines" "globs: [\"**/*\"]" "alwaysApply: true" "---" "" > "$frontmatter_file" - cat "$temp_file" >> "$frontmatter_file" - mv "$frontmatter_file" "$temp_file" - fi - fi - - # Move temp file to target atomically - if ! mv "$temp_file" "$target_file"; then - log_error "Failed to update target file" - rm -f "$temp_file" - return 1 - fi - - return 0 -} -#============================================================================== -# Main Agent File Update Function -#============================================================================== - -update_agent_file() { - local target_file="$1" - local agent_name="$2" - - if [[ -z "$target_file" ]] || [[ -z "$agent_name" ]]; then - log_error "update_agent_file requires target_file and agent_name parameters" - return 1 - fi - - log_info "Updating $agent_name context file: $target_file" - - local project_name - project_name=$(basename "$REPO_ROOT") - local current_date - current_date=$(date +%Y-%m-%d) - - # Create directory if it doesn't exist - local target_dir - target_dir=$(dirname "$target_file") - if [[ ! -d "$target_dir" ]]; then - if ! mkdir -p "$target_dir"; then - log_error "Failed to create directory: $target_dir" - return 1 - fi - fi - - if [[ ! -f "$target_file" ]]; then - # Create new file from template - local temp_file - temp_file=$(mktemp) || { - log_error "Failed to create temporary file" - return 1 - } - - if create_new_agent_file "$target_file" "$temp_file" "$project_name" "$current_date"; then - if mv "$temp_file" "$target_file"; then - log_success "Created new $agent_name context file" - else - log_error "Failed to move temporary file to $target_file" - rm -f "$temp_file" - return 1 - fi - else - log_error "Failed to create new agent file" - rm -f "$temp_file" - return 1 - fi - else - # Update existing file - if [[ ! -r "$target_file" ]]; then - log_error "Cannot read existing file: $target_file" - return 1 - fi - - if [[ ! -w "$target_file" ]]; then - log_error "Cannot write to existing file: $target_file" - return 1 - fi - - if update_existing_agent_file "$target_file" "$current_date"; then - log_success "Updated existing $agent_name context file" - else - log_error "Failed to update existing agent file" - return 1 - fi - fi - - return 0 -} - -#============================================================================== -# Agent Selection and Processing -#============================================================================== - -update_specific_agent() { - local agent_type="$1" - - case "$agent_type" in - claude) - update_agent_file "$CLAUDE_FILE" "Claude Code" - ;; - gemini) - update_agent_file "$GEMINI_FILE" "Gemini CLI" - ;; - copilot) - update_agent_file "$COPILOT_FILE" "GitHub Copilot" - ;; - cursor-agent) - update_agent_file "$CURSOR_FILE" "Cursor IDE" - ;; - qwen) - update_agent_file "$QWEN_FILE" "Qwen Code" - ;; - opencode) - update_agent_file "$AGENTS_FILE" "opencode" - ;; - codex) - update_agent_file "$AGENTS_FILE" "Codex CLI" - ;; - windsurf) - update_agent_file "$WINDSURF_FILE" "Windsurf" - ;; - kilocode) - update_agent_file "$KILOCODE_FILE" "Kilo Code" - ;; - auggie) - update_agent_file "$AUGGIE_FILE" "Auggie CLI" - ;; - roo) - update_agent_file "$ROO_FILE" "Roo Code" - ;; - codebuddy) - update_agent_file "$CODEBUDDY_FILE" "CodeBuddy CLI" - ;; - qodercli) - update_agent_file "$QODER_FILE" "Qoder CLI" - ;; - amp) - update_agent_file "$AMP_FILE" "Amp" - ;; - shai) - update_agent_file "$SHAI_FILE" "SHAI" - ;; - kiro-cli) - update_agent_file "$KIRO_FILE" "Kiro CLI" - ;; - agy) - update_agent_file "$AGY_FILE" "Antigravity" - ;; - bob) - update_agent_file "$BOB_FILE" "IBM Bob" - ;; - generic) - log_info "Generic agent: no predefined context file. Use the agent-specific update script for your agent." - ;; - *) - log_error "Unknown agent type '$agent_type'" - log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli|generic" - exit 1 - ;; - esac -} - -update_all_existing_agents() { - local found_agent=false - - # Check each possible agent file and update if it exists - if [[ -f "$CLAUDE_FILE" ]]; then - update_agent_file "$CLAUDE_FILE" "Claude Code" - found_agent=true - fi - - if [[ -f "$GEMINI_FILE" ]]; then - update_agent_file "$GEMINI_FILE" "Gemini CLI" - found_agent=true - fi - - if [[ -f "$COPILOT_FILE" ]]; then - update_agent_file "$COPILOT_FILE" "GitHub Copilot" - found_agent=true - fi - - if [[ -f "$CURSOR_FILE" ]]; then - update_agent_file "$CURSOR_FILE" "Cursor IDE" - found_agent=true - fi - - if [[ -f "$QWEN_FILE" ]]; then - update_agent_file "$QWEN_FILE" "Qwen Code" - found_agent=true - fi - - if [[ -f "$AGENTS_FILE" ]]; then - update_agent_file "$AGENTS_FILE" "Codex/opencode" - found_agent=true - fi - - if [[ -f "$WINDSURF_FILE" ]]; then - update_agent_file "$WINDSURF_FILE" "Windsurf" - found_agent=true - fi - - if [[ -f "$KILOCODE_FILE" ]]; then - update_agent_file "$KILOCODE_FILE" "Kilo Code" - found_agent=true - fi - - if [[ -f "$AUGGIE_FILE" ]]; then - update_agent_file "$AUGGIE_FILE" "Auggie CLI" - found_agent=true - fi - - if [[ -f "$ROO_FILE" ]]; then - update_agent_file "$ROO_FILE" "Roo Code" - found_agent=true - fi - - if [[ -f "$CODEBUDDY_FILE" ]]; then - update_agent_file "$CODEBUDDY_FILE" "CodeBuddy CLI" - found_agent=true - fi - - if [[ -f "$SHAI_FILE" ]]; then - update_agent_file "$SHAI_FILE" "SHAI" - found_agent=true - fi - - if [[ -f "$QODER_FILE" ]]; then - update_agent_file "$QODER_FILE" "Qoder CLI" - found_agent=true - fi - - if [[ -f "$KIRO_FILE" ]]; then - update_agent_file "$KIRO_FILE" "Kiro CLI" - found_agent=true - fi - - if [[ -f "$AGY_FILE" ]]; then - update_agent_file "$AGY_FILE" "Antigravity" - found_agent=true - fi - if [[ -f "$BOB_FILE" ]]; then - update_agent_file "$BOB_FILE" "IBM Bob" - found_agent=true - fi - - # If no agent files exist, create a default Claude file - if [[ "$found_agent" == false ]]; then - log_info "No existing agent files found, creating default Claude file..." - update_agent_file "$CLAUDE_FILE" "Claude Code" - fi -} -print_summary() { - echo - log_info "Summary of changes:" - - if [[ -n "$NEW_LANG" ]]; then - echo " - Added language: $NEW_LANG" - fi - - if [[ -n "$NEW_FRAMEWORK" ]]; then - echo " - Added framework: $NEW_FRAMEWORK" - fi - - if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then - echo " - Added database: $NEW_DB" - fi - - echo - - log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli]" -} - -#============================================================================== -# Main Execution -#============================================================================== - -main() { - # Validate environment before proceeding - validate_environment - - log_info "=== Updating agent context files for feature $CURRENT_BRANCH ===" - - # Parse the plan file to extract project information - if ! parse_plan_data "$NEW_PLAN"; then - log_error "Failed to parse plan data" - exit 1 - fi - - # Process based on agent type argument - local success=true - - if [[ -z "$AGENT_TYPE" ]]; then - # No specific agent provided - update all existing agent files - log_info "No agent specified, updating all existing agent files..." - if ! update_all_existing_agents; then - success=false - fi - else - # Specific agent provided - update only that agent - log_info "Updating specific agent: $AGENT_TYPE" - if ! update_specific_agent "$AGENT_TYPE"; then - success=false - fi - fi - - # Print summary - print_summary - - if [[ "$success" == true ]]; then - log_success "Agent context update completed successfully" - exit 0 - else - log_error "Agent context update completed with errors" - exit 1 - fi -} - -# Execute main function if script is run directly -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - main "$@" -fi +echo "Plan-derived agent context generation is disabled; maintain AGENTS.md directly." diff --git a/.specify/templates/agent-file-template.md b/.specify/templates/agent-file-template.md index 4cc7fd667..71420a59c 100644 --- a/.specify/templates/agent-file-template.md +++ b/.specify/templates/agent-file-template.md @@ -1,28 +1,6 @@ -# [PROJECT NAME] Development Guidelines +# [PROJECT NAME] Agent Instructions -Auto-generated from all feature plans. Last updated: [DATE] - -## Active Technologies - -[EXTRACTED FROM ALL PLAN.MD FILES] - -## Project Structure - -```text -[ACTUAL STRUCTURE FROM PLANS] -``` - -## Commands - -[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES] - -## Code Style - -[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE] - -## Recent Changes - -[LAST 3 FEATURES AND WHAT THEY ADDED] +Repository-wide instructions are maintained in `AGENTS.md`. Keep this file feature-neutral; feature plans and historical change summaries belong in `specs/`. diff --git a/AGENTS.md b/AGENTS.md index 52e58fcd9..2f8da3ddc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,28 +81,7 @@ Before handing off changes, verify the following when applicable: - New code follows nullable annotations and existing style. - No unrelated files were changed. - -For additional context about technologies to be used, project structure, -shell commands, and other important information, read `specs/008-weaver-ai-copilot/plan.md`. - +## Instruction Maintenance -## Active Technologies -- C# latest, nullable reference types enabled, implicit usings enabled. + `Microsoft.Extensions.Logging`, `Microsoft.AspNetCore.SignalR`, Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, existing Elsa identity/authorization features. (003-live-server-logs) -- Bounded in-memory ring buffer for MVP; no EF Core schema changes. Provider abstraction allows external/shared log backends later. (003-live-server-logs) -- C# latest, nullable reference types enabled, implicit usings enabled. + `Microsoft.Extensions.Logging`, `Microsoft.Extensions.Options`, `Microsoft.AspNetCore.SignalR`, Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, CShells shell feature infrastructure. (004-diagnostics-structured-logs) -- Existing bounded in-memory ring buffer; no EF Core schema changes. Provider abstraction remains available for future shared backends. (004-diagnostics-structured-logs) -- C# latest, nullable reference types enabled, implicit usings enabled. + Existing `Elsa.Diagnostics.StructuredLogs`, `Microsoft.Extensions.Logging`, `Microsoft.Extensions.Options`, `Microsoft.AspNetCore.SignalR`, Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, FluentMigrator runner packages, SQLite ADO.NET provider, and optionally Dapper for relational operations. (005-structured-log-persistence) -- Bounded in-memory store by default; opt-in SQLite durable store through shared relational persistence. SQLite stores `Timestamp` and `ReceivedAt` as UTC ISO-8601 text and stores exception, scope, and property payloads as JSON text. (005-structured-log-persistence) -- C# latest, nullable reference types enabled, implicit usings enabled. + `Microsoft.Extensions.Options`, `Microsoft.AspNetCore.SignalR`, Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, Elsa shell feature infrastructure, and existing Elsa identity/authorization patterns. (006-diagnostics-console-logs) -- Bounded in-memory recent buffer and bounded subscriber queues by default; no durable database schema. Providers receive redacted content only. (006-diagnostics-console-logs) -- C# latest, nullable reference types enabled, implicit usings enabled. + Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, existing Elsa identity/authorization patterns, Elsa workflow input metadata, `Microsoft.Extensions.Configuration`, `Microsoft.AspNetCore.DataProtection`, EF Core persistence infrastructure, mediator notifications, and optional JavaScript expression integration. (007-secrets-module) -- In-memory store for tests/development; Elsa-managed encrypted store with EF Core persistence for production; configuration-backed read-only store for deployment-managed values. No cloud vault or OS certificate store provider in v1. (007-secrets-module) -- C# latest, nullable reference types enabled, implicit usings enabled; paired Studio Blazor/Razor module work in the Studio repository. + Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, existing identity/authorization and tenancy services, workflow definition/instance abstractions, diagnostics/log abstractions, `Microsoft.Extensions.Options`, `Microsoft.Extensions.Logging`, OpenTelemetry, `System.Text.Json`, SignalR or SSE streaming, GitHub Copilot SDK isolated behind `Elsa.AI.Copilot`, and headless Copilot CLI JSON-RPC integration. (008-weaver-ai-copilot) -- Configurable conversation/session retention with in-memory support for development and tests; durable proposal and audit stores required for MVP using Elsa persistence provider abstractions and an EF Core provider package for production. (008-weaver-ai-copilot) - -## Recent Changes -- 008-weaver-ai-copilot: Captures Weaver as a server-hosted, provider-isolated AI copilot platform with Studio chat, governed tools, proposal-only workflow mutations, audit, and extensibility. -- 006-diagnostics-console-logs: Plans raw stdout/stderr console capture with redaction-before-provider boundaries, bounded in-memory recent/live buffers, REST backfill/source endpoints, and a SignalR live hub. -- 005-structured-log-persistence: Plans pluggable structured log storage with in-memory default and opt-in SQLite persistence using FluentMigrator. -- 004-diagnostics-structured-logs: Refactors the unpublished server logs module into diagnostics structured logs and preserves bounded structured `ILogger` capture. -- 003-live-server-logs: Added C# latest, nullable reference types enabled, implicit usings enabled. + `Microsoft.Extensions.Logging`, `Microsoft.AspNetCore.SignalR`, Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, existing Elsa identity/authorization features. +- Keep this file limited to stable, repository-wide guidance. Feature-specific plans and historical change summaries belong in `specs/`, not here. +- Agent-specific instruction files should defer to this file instead of duplicating or generating plan-derived content. diff --git a/CLAUDE.md b/CLAUDE.md index d64573116..4f18cfcd7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,36 +1,3 @@ -# main Development Guidelines +# Elsa Core Agent Instructions -Auto-generated from all feature plans. Last updated: 2026-04-24 - -## Active Technologies - -- C# latest (`latest`), nullable reference types enabled, implicit usings enabled — per `src/Directory.Build.props`. + `Elsa.Workflows.Runtime`, `Elsa.Workflows.Runtime.Distributed`, `Elsa.Hosting.Management` (existing heartbeat), `Elsa.Http` and `Elsa.Scheduling` (first ingress-source adapters), `Elsa.Api.Common` (`ElsaEndpoint` on FastEndpoints), `Elsa.Features` (`IShellFeature`), `Microsoft.Extensions.DependencyInjection`, `Elsa.Mediator`. (002-graceful-shutdown) - -## Project Structure - -```text -src/ -tests/ -``` - -## Commands - -# Add commands for C# latest (`latest`), nullable reference types enabled, implicit usings enabled — per `src/Directory.Build.props`. - -## Code Style - -C# latest (`latest`), nullable reference types enabled, implicit usings enabled — per `src/Directory.Build.props`.: Follow standard conventions - -## Recent Changes - -- 002-graceful-shutdown: Added C# latest (`latest`), nullable reference types enabled, implicit usings enabled — per `src/Directory.Build.props`. + `Elsa.Workflows.Runtime`, `Elsa.Workflows.Runtime.Distributed`, `Elsa.Hosting.Management` (existing heartbeat), `Elsa.Http` and `Elsa.Scheduling` (first ingress-source adapters), `Elsa.Api.Common` (`ElsaEndpoint` on FastEndpoints), `Elsa.Features` (`IShellFeature`), `Microsoft.Extensions.DependencyInjection`, `Elsa.Mediator`. - - -## Agent Operating Principles - -- Do not assume, hide confusion, or flatten uncertainty; surface questions, constraints, and tradeoffs explicitly. -- Write the minimum code that solves the defined problem; do not add speculative abstractions, features, or cleanup. -- Touch only the files and behavior required for the task; clean up only issues introduced by your own changes. -- Define success criteria before implementation, then iterate until the criteria are verified or clearly state what could not be verified. - - +Use the canonical repository guidance in [AGENTS.md](AGENTS.md). Keep feature-specific plan details in `specs/`; they are not copied into this file.