Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/verify-guide.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Verify Navigation Guide

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
verify:
name: Verify Navigation Guide
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Build agentic-navigation-guide
run: cargo build --release
- name: Verify navigation guide
run: cargo run --release -- verify --github-actions-check
19 changes: 16 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ cargo run -- check --guide path/to/guide.md
cargo run -- verify
cargo run -- verify --guide path/to/guide.md --root /path/to/root

# Verify in GitHub Actions mode (concise output, file:line format)
cargo run -- verify --github-actions-check

# Recursively verify all navigation guides (for monorepos)
cargo run -- verify --recursive
cargo run -- verify --recursive --guide-name GUIDE.md --exclude target --exclude node_modules

# Initialize new guide file
cargo run -- init --output AGENTIC_NAVIGATION_GUIDE.md
```
Expand All @@ -60,6 +67,8 @@ This is a CLI tool for verifying hand-written navigation guides against filesyst

4. **Dumper** (`src/dumper.rs`): Generates navigation guides from directory structures, with support for depth limiting and glob exclusion patterns.

5. **Recursive** (`src/recursive.rs`): Provides recursive guide discovery and batch verification for monorepos with nested navigation guides. Uses WalkDir to find all guide files and verifies each relative to its parent directory.

### Data Flow

1. **Input**: Markdown files containing `<agentic-navigation-guide>` blocks
Expand All @@ -72,8 +81,11 @@ This is a CLI tool for verifying hand-written navigation guides against filesyst

- `FilesystemItem`: Enum representing File, Directory, or Symlink
- `NavigationGuideLine`: Parsed line with indent level and filesystem item
- `NavigationGuide`: Complete guide with items and optional prologue/epilogue
- `ExecutionMode`: Default, PostToolUse (exit code 2), or PreCommitHook
- `NavigationGuide`: Complete guide with items, optional prologue/epilogue, and ignore flag
- The `ignore` field indicates whether the guide should be skipped during verification
- Set using `<agentic-navigation-guide ignore=true>` in the opening tag
- Useful for documentation examples that shouldn't be validated
- `ExecutionMode`: Default, PostToolUse (exit code 2), PreCommitHook, or GitHubActions

### Error Handling

Expand All @@ -86,6 +98,7 @@ This is a CLI tool for verifying hand-written navigation guides against filesyst
These environment variables are used to configure the `agentic-navigation-guide` tool's behavior:

- `AGENTIC_NAVIGATION_GUIDE_LOG_MODE`: Set to "quiet", "verbose", or "default"
- `AGENTIC_NAVIGATION_GUIDE_EXECUTION_MODE`: Set to "post-tool-use", "pre-commit-hook", or "default"
- `AGENTIC_NAVIGATION_GUIDE_EXECUTION_MODE`: Set to "post-tool-use", "pre-commit-hook", "github-actions", or "default"
- `AGENTIC_NAVIGATION_GUIDE_PATH`: Default path to guide file
- `AGENTIC_NAVIGATION_GUIDE_ROOT`: Default root directory for operations
- `AGENTIC_NAVIGATION_GUIDE_NAME`: Default guide filename for recursive mode (e.g., "GUIDE.md")
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "agentic-navigation-guide"
version = "0.1.2"
version = "0.1.3"
edition = "2021"
authors = ["plx <plxgithub@gmail.com>"]
description = "A CLI tool for verifying hand-written navigation guides against filesystem structure"
Expand Down
136 changes: 129 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The validation can be done in a stand-alone way, and also has special support fo
A "navigation guide" looks like this:

```
<agentic-navigation-guide>
<agentic-navigation-guide ignore=true>
- src/
- main.rs # Main entry point
- lib.rs # Core logic goes here
Expand Down Expand Up @@ -53,7 +53,7 @@ Note that it's *not* an error to omit files and directories from the guide, but
You can use `...` as a placeholder to indicate that there are additional files or directories not explicitly listed:

```
<agentic-navigation-guide>
<agentic-navigation-guide ignore=true>
- src/
- main.rs # Entry point
- ... # Other source files
Expand All @@ -68,9 +68,48 @@ Rules for placeholders:
- Written as `...` (three dots)
- May have an optional comment after it
- Cannot have child elements nested under them
- Must refer to at least one unlisted item in the parent directory
- **With a comment**: Allowed in any directory, even if all items are listed or the directory is empty (useful for indicating future items)
- **Without a comment**: Must refer to at least one unlisted item in the parent directory (useful for omitting existing items)
- Cannot be adjacent to another `...` entry (must have at least one non-placeholder between them)
- Cannot be used in an empty directory

The distinction between commented and uncommented placeholders enables two important use cases:

```
<agentic-navigation-guide ignore=true>
- src/
- main.rs
- ... # Represents lib.rs, utils.rs, etc. that exist but aren't listed
- plans/
- phases/
- phase-01-scaffolding.md # Phase 1 - COMPLETED
- ... # Plans for future phases will appear here
</agentic-navigation-guide>
```

In this example:
- The first `...` in `src/` has a comment and there ARE unmentioned files (lib.rs, utils.rs) - represents omitted existing items
- The second `...` in `phases/` has a comment but phase-01-scaffolding.md is the ONLY file - represents future items that don't exist yet

### Ignoring Guides

You can mark a navigation guide to be ignored during verification by adding an `ignore` attribute to the opening tag:

```markdown
<agentic-navigation-guide ignore=true>
- example/
- file.rs
</agentic-navigation-guide>
```

This is particularly useful for:
- **Documentation examples**: Example guides in README files that should not be validated
- **Invalid examples**: Intentionally incorrect guides used to demonstrate error cases
- **Template files**: Guide templates that may not match the current filesystem

The tool accepts both `ignore=true` and `ignore="true"` formats. When a guide is ignored, the tool will:
- Skip all syntax and semantic validation
- Emit a warning that the guide was skipped
- Provide an additional note if the ignored guide is in a standalone `AGENTIC_NAVIGATION_GUIDE.md` file

## Suggested Usage

Expand Down Expand Up @@ -122,13 +161,96 @@ To set it up as a post-tool-use-hook, you can update your `~/.claude/settings.js
}
```

## GitHub Actions Integration

To use the tool as a CI check in GitHub Actions, add a job to your workflow:

```yaml
verify-navigation-guide:
name: Verify Navigation Guide
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install agentic-navigation-guide
run: cargo install agentic-navigation-guide
- name: Verify installation
run: agentic-navigation-guide --version
- name: Verify navigation guide
run: agentic-navigation-guide verify --github-actions-check
```

The `--github-actions-check` flag provides:
- Concise output on success ("✓ Navigation guide verified")
- Detailed error messages with file:line references
- Exit code 1 on failure (standard for CI checks)
- Visual indicators (emoji) for quick scanning

You can also set the execution mode via environment variable:
```yaml
- name: Verify navigation guide
run: agentic-navigation-guide verify
env:
AGENTIC_NAVIGATION_GUIDE_EXECUTION_MODE: github-actions
```

## Recursive Verification for Monorepos

For monorepos or projects with nested navigation guides, you can use the `--recursive` flag to automatically discover and verify all guide files:

```bash
# Recursively verify all AGENTIC_NAVIGATION_GUIDE.md files
agentic-navigation-guide verify --recursive

# Use a custom guide name (e.g., GUIDE.md)
agentic-navigation-guide verify --recursive --guide-name GUIDE.md

# Exclude directories from the search
agentic-navigation-guide verify --recursive --exclude target --exclude node_modules
```

### Example Monorepo Structure

```
AGENTIC_NAVIGATION_GUIDE.md # Root-level guide
CLAUDE.md
/backend/
AGENTIC_NAVIGATION_GUIDE.md # Backend guide (verified relative to /backend/)
CLAUDE.md
/services/
/sso/
AGENTIC_NAVIGATION_GUIDE.md # SSO service guide (verified relative to /backend/services/sso/)
CLAUDE.md
/taskrunner/
AGENTIC_NAVIGATION_GUIDE.md # Taskrunner guide (verified relative to /backend/services/taskrunner/)
CLAUDE.md
/frontend/
AGENTIC_NAVIGATION_GUIDE.md # Frontend guide (verified relative to /frontend/)
CLAUDE.md
/consumer/
AGENTIC_NAVIGATION_GUIDE.md # Consumer app guide (verified relative to /frontend/consumer/)
CLAUDE.md
/internal/
AGENTIC_NAVIGATION_GUIDE.md # Internal app guide (verified relative to /frontend/internal/)
CLAUDE.md
```

Each guide is verified relative to its parent directory, allowing you to maintain focused navigation guides for different parts of your codebase.

### Recursive Verification Features

- **Automatic Discovery**: Finds all guide files matching the specified name throughout the directory tree
- **Relative Verification**: Each guide is verified against its parent directory as the root
- **Custom Names**: Support for uniform custom guide filenames (e.g., `--guide-name GUIDE.md`)
- **Exclusion Patterns**: Skip directories like `target`, `node_modules`, `.git` using glob patterns
- **Aggregated Results**: Shows summary of all verified guides with pass/fail counts
- **Execution Modes**: Works with all execution modes (default, post-tool-use, pre-commit-hook, GitHub Actions)

## Future Roadmap

This is an early preview of the tool, so there are a few rough edges. Potential future steps:

- [ ] support for auto-installing the hook (e.g. auto-editing your settings to include it)
- [ ] support for auto-generating the hook (e.g. suggested prompts/commands to have your agent write the guide comments)
- [ ] support for nested guides
- [x] support for nested guides (completed - use `--recursive` flag)
- [ ] inspecting the post-tool-use-hook json and skipping unnecessary work

Note that the tool is already configurable-enough it can be used with nested guides if invoked with the right arguments—the part that's missing is good ergonomics to make it work automagically.
66 changes: 64 additions & 2 deletions Specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ Thus, for example, a minimal `AGENTIC_NAVIGATION_GUIDE.md` file might look like
</agentic-navigation-guide>
```

The opening tag may optionally include an `ignore` attribute to indicate that the guide should be skipped during verification:

```markdown
<agentic-navigation-guide ignore=true>
- src/
- main.rs
- Cargo.toml
</agentic-navigation-guide>
```

This is particularly useful for documentation examples that should not be validated against the actual filesystem.

...but it could also look like this:

```markdown
Expand All @@ -63,6 +75,10 @@ Here are the rules of the above format, spelled out in much fuller detail:

- the navigation guide document must be written in markdown
- the navigation guide *must* include the "sentinel" markers `<agentic-navigation-guide>` and `</agentic-navigation-guide>`
- the opening marker may optionally include an `ignore` attribute: `<agentic-navigation-guide ignore=true>` or `<agentic-navigation-guide ignore="true">`
- guides with `ignore=true` are skipped during verification
- this is useful for documentation examples that should not be validated
- a warning is emitted when skipping an ignored guide
- there must be only a single `agentic-navigation-guide` block within the document
- the contents of the `agentic-navigation-guide` must:
- be a single unordered list with no other content
Expand Down Expand Up @@ -108,6 +124,41 @@ In addition to the above syntactic requirements, the navigation guide must also

As has been mentioned, the navigation guide need not be a *complete* description of the filesystem; it's ok if it *omits* files and directories.

### Details: Placeholder Semantic Validation

Placeholder entries (`...`) have special semantic validation rules that depend on whether they include a comment:

**Placeholders WITH a comment:**
- Allowed in any directory, even if all items are already listed in the guide
- Allowed in empty directories
- The comment describes the meaning of the placeholder (either omitted existing items OR future items that don't yet exist)
- Use case: Indicating planned future files/directories, as in:
```markdown
- plans/
- phases/
- phase-01-scaffolding.md # COMPLETED
- ... # Plans for future phases will appear here
```

**Placeholders WITHOUT a comment:**
- Must refer to at least one item in the parent directory that exists on the filesystem but is not explicitly listed in the guide
- Cannot be used in empty directories
- The placeholder's meaning is implicit: it represents the unlisted items
- Use case: Omitting details about existing files while acknowledging their presence, as in:
```markdown
- src/
- main.rs
- ...
```

Note: here the uncommented `...` in `src/` represents files like `lib.rs`, `types.rs`, etc. that *do exist* but aren't listed in the guide.

This distinction enables two important workflows:
1. **Documenting existing codebases**: Use uncommented placeholders to acknowledge existing files without listing every detail
2. **Planning future development**: Use commented placeholders to document intended future structure before files exist

The validation logic checks each placeholder independently. In a directory with multiple placeholders, each is validated according to its own comment status. All placeholders in a given directory check against the same set of "mentioned items" (the explicitly-listed files/directories at that level).

## Component: `agentic-navigation-guide`

The `agentic-navigation-guide` crate provides an eponynous CLI tool with several subcommands (which we will outline below). The options common to *all* commands are:
Expand Down Expand Up @@ -163,6 +214,7 @@ Named Arguments:

- `--post-tool-use-hook`: indicates we're being invoked as a post-tool-hook by claude code
- `--pre-commit-hook`: indicates we're being invoked as a pre-commit-hook by git
- `--github-actions-check`: indicates we're being invoked as a GitHub Actions check
- `--guide <path>`: the path to the `AGENTIC_NAVIGATION_GUIDE.md` file

If `--guide` is not specified, the following defaults are used, in this order of precedence:
Expand All @@ -171,7 +223,7 @@ If `--guide` is not specified, the following defaults are used, in this order of
- the file in the current directory named by the `AGENTIC_NAVIGATION_GUIDE_NAME` environment variable, if set
- `AGENTIC_NAVIGATION_GUIDE.md` in the current directory

Internally these can be represented as a 3-way "mode" enum like `default | post-tool-use | pre-commit-hook`; the value of this enum can also be controlled by an environment variable (e.g. `AGENTIC_NAVIGATION_GUIDE_EXECUTION_MODE`).
Internally these can be represented as a 4-way "mode" enum like `default | post-tool-use | pre-commit-hook | github-actions`; the value of this enum can also be controlled by an environment variable (e.g. `AGENTIC_NAVIGATION_GUIDE_EXECUTION_MODE`).

There is a single positional argument: the path to the `AGENTIC_NAVIGATION_GUIDE.md` file (default, if unspecified: the file at the `AGENTIC_NAVIGATION_GUIDE_PATH` environment variable, if set; otherwise, `AGENTIC_NAVIGATION_GUIDE.md` in the current directory).

Expand All @@ -195,7 +247,17 @@ The messages for syntactic errors should be identical to those for `check`. The

## Details: Execution Modes

We want to make sure the internals are aware of when they're being run as a pre-commit hook, a post-tool-use hook, or in "default" mode. For now the main distinction is that we need to be careful to return error code **2** when we fail on a post-tool-use hook invocation, since that's what claude code expects.
We want to make sure the internals are aware of the execution context to provide appropriate output:

- **Default**: Standard mode with full error messages, exit code 1 on failure
- **Post-Tool-Use**: Running as a Claude Code hook, exit code **2** on failure (as Claude Code expects)
- **Pre-Commit-Hook**: Running as a git pre-commit hook, exit code 1 on failure
- **GitHub-Actions**: Running as a CI check with:
- Concise success messages ("✓ Navigation guide verified" instead of full text)
- Error messages in `file:line: error` format for easy IDE integration
- Visual indicators (emoji) for quick scanning in CI logs
- Line content displayed below each error
- Exit code 1 on failure

## Details: Rust

Expand Down
Loading