-
Notifications
You must be signed in to change notification settings - Fork 37
feat: add AGENTS.md symlink support with comprehensive testing #429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| name: Test AGENTS.md Symlink | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - 'AGENTS.md' | ||
| - 'CLAUDE.md' | ||
| - 'tests/test_agents_md_symlink.sh' | ||
| - '.github/workflows/test-agents-md-symlink.yml' | ||
| push: | ||
| branches: | ||
| - main | ||
| paths: | ||
| - 'AGENTS.md' | ||
| - 'CLAUDE.md' | ||
| - 'tests/test_agents_md_symlink.sh' | ||
|
|
||
| jobs: | ||
| test-symlink: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v5 | ||
|
|
||
| - name: Validate AGENTS.md symlink | ||
| run: | | ||
| chmod +x tests/test_agents_md_symlink.sh | ||
| ./tests/test_agents_md_symlink.sh | ||
|
|
||
| - name: Test cross-platform compatibility | ||
| run: | | ||
| echo "Testing symlink on Linux..." | ||
|
|
||
| # Verify symlink properties | ||
| ls -la AGENTS.md | ||
|
|
||
| # Verify git stores it correctly | ||
| git ls-files -s AGENTS.md | ||
|
|
||
| # Verify content is accessible | ||
| head -n 5 AGENTS.md | ||
|
|
||
| echo "✅ Symlink works correctly on Linux" | ||
|
|
||
| - name: Validate git tracking | ||
| run: | | ||
| # Check that AGENTS.md is in git index | ||
| if git ls-files --error-unmatch AGENTS.md > /dev/null 2>&1; then | ||
| echo "✅ AGENTS.md is tracked by git" | ||
| else | ||
| echo "❌ ERROR: AGENTS.md is not tracked by git" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Check that it's stored as a symlink in git | ||
| MODE=$(git ls-files -s AGENTS.md | awk '{print $1}') | ||
| if [ "$MODE" = "120000" ]; then | ||
| echo "✅ AGENTS.md is stored as symlink (mode 120000)" | ||
| else | ||
| echo "❌ ERROR: AGENTS.md is not stored as symlink (mode: $MODE)" | ||
| exit 1 | ||
| fi | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| CLAUDE.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # Tests | ||
|
|
||
| This directory contains project-level tests for the Ambient Code Platform. | ||
|
|
||
| ## Test Structure | ||
|
|
||
| - `integration/` - Integration tests requiring real Kubernetes clusters | ||
| - `test_agents_md_symlink.sh` - Validates AGENTS.md symlink for Cursor compatibility | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about generalizing this to something like |
||
|
|
||
| ## AGENTS.md Symlink Test | ||
|
|
||
| The `test_agents_md_symlink.sh` script validates that the `AGENTS.md` → `CLAUDE.md` symlink works correctly for Cursor and other AI coding tools. | ||
|
|
||
| ### What It Tests | ||
|
|
||
| 1. ✅ AGENTS.md exists and is a valid symlink | ||
| 2. ✅ Symlink points to CLAUDE.md | ||
| 3. ✅ Content is readable through symlink | ||
| 4. ✅ Content matches CLAUDE.md exactly | ||
| 5. ✅ File is tracked by git correctly (mode 120000) | ||
| 6. ✅ Contains expected project context | ||
| 7. ✅ All required documentation sections exist | ||
| 8. ✅ File size is reasonable | ||
|
Comment on lines
+12
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And all of this stuff is already described in the test itself - what value is there in duplicating it? It can only get out of date. |
||
|
|
||
| ### Running Locally | ||
|
|
||
| ```bash | ||
| ./tests/test_agents_md_symlink.sh | ||
| ``` | ||
|
|
||
| ### CI Integration | ||
|
|
||
| The test runs automatically in GitHub Actions on PRs that modify: | ||
| - `AGENTS.md` | ||
| - `CLAUDE.md` | ||
| - `tests/test_agents_md_symlink.sh` | ||
| - `.github/workflows/test-agents-md-symlink.yml` | ||
|
|
||
| See `.github/workflows/test-agents-md-symlink.yml` for the CI workflow. | ||
|
|
||
| ### Why a Symlink? | ||
|
|
||
| **Problem**: Claude Code uses `CLAUDE.md`, Cursor uses `AGENTS.md` | ||
|
|
||
| **Solution**: Symlink eliminates duplication and maintenance overhead | ||
|
|
||
| **Benefits**: | ||
| - Zero maintenance (single source of truth) | ||
| - No sync issues between files | ||
| - Git tracks symlinks correctly across platforms | ||
| - Works on macOS, Linux, WSL, and Windows (with symlink support) | ||
|
|
||
| ### Cross-Platform Notes | ||
|
|
||
| - **macOS/Linux/WSL**: Native symlink support ✅ | ||
| - **Windows**: Git for Windows handles symlinks correctly when cloned ✅ | ||
| - **Git behavior**: Stores symlinks as special objects (mode 120000), content is the link target | ||
|
|
||
| ## Component-Specific Tests | ||
|
|
||
| See component README files for testing details: | ||
|
|
||
| - Backend: `components/backend/tests/` | ||
| - Frontend: `components/frontend/` (Cypress e2e tests) | ||
| - Operator: `components/operator/` (controller tests) | ||
| - Claude Runner: `components/runners/claude-code-runner/tests/` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Test that AGENTS.md symlink works for Cursor and other AI tools | ||
| # This validates that: | ||
| # 1. AGENTS.md exists and is a valid symlink | ||
| # 2. It points to CLAUDE.md | ||
| # 3. Content is readable and identical to CLAUDE.md | ||
| # 4. File is tracked by git correctly | ||
|
Comment on lines
+3
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This testing feels pretty excessive for something so simple. What I think would be enough testing and more useful would be to verify some agent other than claude (like goose or whatever) running on this repo has successfully read in the content. |
||
|
|
||
| set -e | ||
|
|
||
| echo "Testing AGENTS.md symlink..." | ||
|
|
||
| # Test 1: Check that AGENTS.md exists | ||
| echo -n "✓ Checking AGENTS.md exists... " | ||
| if [ ! -e AGENTS.md ]; then | ||
| echo "FAILED" | ||
| echo "Error: AGENTS.md does not exist" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 2: Check that AGENTS.md is a symlink | ||
| echo -n "✓ Checking AGENTS.md is a symlink... " | ||
| if [ ! -L AGENTS.md ]; then | ||
| echo "FAILED" | ||
| echo "Error: AGENTS.md is not a symlink" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 3: Check that symlink points to CLAUDE.md | ||
| echo -n "✓ Checking symlink target is CLAUDE.md... " | ||
| TARGET=$(readlink AGENTS.md) | ||
| if [ "$TARGET" != "CLAUDE.md" ]; then | ||
| echo "FAILED" | ||
| echo "Error: AGENTS.md points to '$TARGET', expected 'CLAUDE.md'" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 4: Check that CLAUDE.md exists (symlink target) | ||
| echo -n "✓ Checking CLAUDE.md exists... " | ||
| if [ ! -f CLAUDE.md ]; then | ||
| echo "FAILED" | ||
| echo "Error: CLAUDE.md (symlink target) does not exist" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 5: Check that content is readable through symlink | ||
| echo -n "✓ Checking AGENTS.md content is readable... " | ||
| if ! cat AGENTS.md > /dev/null 2>&1; then | ||
| echo "FAILED" | ||
| echo "Error: Cannot read content through AGENTS.md symlink" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 6: Check that content is identical to CLAUDE.md | ||
| echo -n "✓ Checking AGENTS.md content matches CLAUDE.md... " | ||
| if ! diff -q AGENTS.md CLAUDE.md > /dev/null 2>&1; then | ||
| echo "FAILED" | ||
| echo "Error: AGENTS.md content does not match CLAUDE.md" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 7: Check that file is tracked by git | ||
| echo -n "✓ Checking AGENTS.md is tracked by git... " | ||
| if ! git ls-files --error-unmatch AGENTS.md > /dev/null 2>&1; then | ||
| echo "WARNING" | ||
| echo "Warning: AGENTS.md is not tracked by git (will be added in commit)" | ||
| else | ||
| echo "OK" | ||
| fi | ||
|
|
||
| # Test 8: Validate that symlink contains expected project context | ||
| echo -n "✓ Checking AGENTS.md contains project context... " | ||
| if ! grep -q "Ambient Code Platform" AGENTS.md; then | ||
| echo "FAILED" | ||
| echo "Error: AGENTS.md does not contain expected project context" | ||
| exit 1 | ||
| fi | ||
| echo "OK" | ||
|
|
||
| # Test 9: Validate key sections exist | ||
| echo -n "✓ Checking key sections exist... " | ||
| REQUIRED_SECTIONS=( | ||
| "Project Overview" | ||
| "Development Commands" | ||
| "Key Architecture Patterns" | ||
| "Backend and Operator Development Standards" | ||
| "Frontend Development Standards" | ||
| ) | ||
|
|
||
| for section in "${REQUIRED_SECTIONS[@]}"; do | ||
| if ! grep -q "$section" AGENTS.md; then | ||
| echo "FAILED" | ||
| echo "Error: Section '$section' not found in AGENTS.md" | ||
| exit 1 | ||
| fi | ||
| done | ||
| echo "OK" | ||
|
|
||
| # Test 10: Check file size is reasonable (should match CLAUDE.md) | ||
| echo -n "✓ Checking file size is reasonable... " | ||
| SIZE=$(wc -c < AGENTS.md) | ||
| if [ "$SIZE" -lt 1000 ]; then | ||
| echo "FAILED" | ||
| echo "Error: AGENTS.md content is too small ($SIZE bytes), symlink may be broken" | ||
| exit 1 | ||
| fi | ||
| echo "OK (${SIZE} bytes)" | ||
|
|
||
| echo "" | ||
| echo "✅ All tests passed! AGENTS.md symlink is working correctly." | ||
| echo " - Symlink: AGENTS.md -> CLAUDE.md" | ||
| echo " - Content size: ${SIZE} bytes" | ||
| echo " - Cursor and other AI tools can use AGENTS.md" | ||
| echo "" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
er...a whole github actions workflow to verify a file is in the git repository?
That feels like massive overkill?