Skip to content

[Bug]: .augment/rules rule files are silently ignored when the rules directory (or the individual .md files inside it) are symlinks #154

Description

@RunDevelopmentSk

What happened?

When .augment/rules (or files inside it) are symlinks rather than regular files/directories, auggie detects zero rules — no error, no warning, just silently skipped. Real (non-symlinked) files in the exact same location are detected correctly. The same symlink pattern works fine for custom commands .augment/commands), so this looks specific to the rules-discovery code path.

What did you expect to happen?

Symlinked rule files (or a symlinked rules directory) should be resolved to their target and loaded like any regular file or directory.

Steps to reproduce

  1. Create a workspace-level rule via a symlinked directory:

    mkdir -p real-rules
    cat > real-rules/test.md << 'EOF'
    ---
    description: test rule
    type: always_apply
    ---
    # Test rule
    EOF
    ln -s ../real-rules .augment/rules
    auggie rules list

    Result: always_apply: 0 — the rule is not found.

  2. Alternatively, make .augment/rules a real directory but symlink the individual .md file into it:

    mkdir .augment/rules
    ln -s ../../real-rules/test.md .augment/rules/test.md
    auggie rules list

    Result: still always_apply: 0.

  3. Control case — put a real (non-symlinked) file with identical frontmatter directly in .augment/rules:

    cat > .augment/rules/test-real.md << 'EOF'
    ---
    description: test rule real file
    type: always_apply
    ---
    # Test rule
    EOF
    auggie rules list

    Result: always_apply: 1, correctly listing .augment/rules/test-real.md.

  4. Decisive A/B test — put one real file and one symlinked file side by side in the same (real) .augment/rules direct
    ory:

    .augment/rules/
      test-real.md        (regular file)
      test-symlink.md -> ../../real-rules/other.md   (symlink, same valid frontmatter)
    

    auggie rules list finds only test-real.md; test-symlink.md is completely invisible to it (not even reported a
    s an invalid/skipped rule).

Auggie version

0.32.0

Request ID

c8e2f1a8-f868-4dec-b32a-772ec129ac96

Environment details

Environment
  • auggie version: 0.32.0 (commit eb99b871)
  • Node.js: v24.18.0
  • OS: Ubuntu 24.04.3 LTS (Noble Numbat), Linux 6.8.0-134-generic, x86_64

Anything else we need to know?

Likely root cause

This matches a well-known Node.js fs.Dirent gotcha: when a directory is scanned via

fs.readdirSync(dir, { withFileTypes: true })

the returned Dirent.isFile() / Dirent.isDirectory() are derived from the raw directory-entry type (d_type) and are not resolved through the symlink — for a symlinked entry pointing at a directory or a regular file, both isFile() and isDirectory() return false (only isSymbolicLink() is true). Confirmed directly in this environment:

const fs = require('fs');
fs.readdirSync('.augment', { withFileTypes: true })
  .forEach(e => console.log(e.name, e.isDirectory(), e.isSymbolicLink()));
// rules   false   true

If the rules-discovery code filters entries with dirent.isFile() / dirent.isDirectory() (instead of resolving via fs.statSync(), which does follow symlinks, or explicitly handling dirent.isSymbolicLink() with a realpath/stat fallback), every symlinked rule file or symlinked rules directory is silently skipped. The commands loader apparently does not have this issue, suggesting it uses a different (symlink-safe) traversal method.

Suggested fix

In the rules-discovery code, resolve directory entries via fs.statSync(fullPath) (or check dirent.isSymbolicLink() and follow up with fs.realpathSync/fs.statSync) instead of relying solely on Dirent.isFile()/isDirectory() from readdir({ withFileTypes: true }).

Why this matters

Symlinking a shared rules directory into .augment/rules (e.g. .augment/rules -> ../shared/rules) is a common pattern for projects that want one source of truth for instructions shared across multiple AI coding agents (Auggie, Claude Code, etc.). Right now this silently produces zero active rules with no warning, which is easy to miss (looks like everything is configured correctly — ls -la shows the files, cat on them works — only auggie rules list / /status reveals the problem).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions