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
149 changes: 149 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
## Summary

<!-- Provide a brief overview of the changes in this PR. What feature/fix/improvement does this introduce? -->

## Changelog

<!-- CRITICAL: This section is the source of truth for CHANGELOG.md.
generate-changelog.sh extracts these categorized bullets verbatim
into the release changelog. Write carefully — this IS the changelog.

AUDIENCE: Users and operators. Write from their perspective.

INCLUDE: new features, changed behavior, breaking changes, fixed bugs,
new/removed config, new dependencies users need to know about.

EXCLUDE: internal refactors, test additions, code cleanup, CI changes,
regenerated files, implementation details (unreachable!() arms, import
reordering, cargo_bin migration, cfg gates, etc.). Document those in
the PR body text or Files Modified section — NOT here.

RULES:
- 1-5 bullets per PR. Fewer is better. One-line fixes get one bullet.
- Delete empty ### sections entirely — don't leave blank categories.
- Each bullet starts with a verb: Add, Fix, Change, Remove, Deprecate.
- Don't duplicate the PR title — expand on it or provide context.
- If the PR has NO user-facing changes (pure refactor, test-only, CI), leave this section empty or omit it. The PR still
appears in git history; it just won't clutter the changelog. -->

### Added

-

### Changed

-

### Fixed

-

### Documentation

-

## Type of Change

<!-- Check the type that applies to this PR -->

- [ ] `feat`: New feature (non-breaking change which adds functionality)
- [ ] `fix`: Bug fix (non-breaking change which fixes an issue)
- [ ] `refactor`: Code refactoring (no functional changes)
- [ ] `perf`: Performance improvement
- [ ] `docs`: Documentation update
- [ ] `test`: Adding or updating tests
- [ ] `chore`: Maintenance tasks (dependencies, config, etc.)
- [ ] `ci`: CI/CD configuration changes
- [ ] `style`: Code style/formatting changes
- [ ] `build`: Build system changes
- [ ] `BREAKING CHANGE`: Breaking API change (requires major version bump)

## Related Issues/Stories

<!-- Link to related issues, stories, or documentation -->

- Story:
- Issue:
- Architecture:
- Related PRs:

## Testing

<!-- Describe the testing approach and results -->

- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing completed
- [ ] All tests passing

**Test Summary:**

- Unit tests: X passing
- Integration tests: Y passing
- Coverage: Z%

## Files Modified

<!-- List the main files modified in this PR -->

**Modified:**

**Created:**

**Deleted:**

## Key Features

<!-- Optional: Highlight key features or capabilities introduced -->

-

## Benefits

<!-- Optional: Describe the benefits (performance, security, compliance, UX, etc.) -->

-

## Breaking Changes

<!-- If this PR contains breaking changes, describe them and the migration path -->

- [ ] No breaking changes
- [ ] Breaking changes described below:

## Deployment Notes

<!-- Any special deployment considerations, migrations, or configuration changes needed -->

- [ ] No special deployment steps required
- [ ] Deployment steps documented below:

## Screenshots/Recordings

<!-- Optional: Add screenshots or recordings for UI changes -->

## Checklist

- [ ] Code follows project conventions and style guidelines
- [ ] Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/)
- [ ] Self-review of code completed
- [ ] Tests added/updated and passing
- [ ] No new warnings or errors introduced
- [ ] Changes are backward compatible (or breaking changes documented)

## Additional Context

<!-- Optional: Add any additional context, screenshots, or information -->

---

<!--
PR Title Format: <type>(<scope>): <description>

Examples:
- feat(auth): add OAuth2 authentication provider
- fix(api): resolve rate limiting edge case
- docs(readme): update installation instructions
- refactor(db): optimize query performance
- chore(deps): upgrade to bun 1.3.1
-->
3 changes: 3 additions & 0 deletions .github/rulesets/protect-main.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
},
{
"context": "guard-provenance / check-provenance"
},
{
"context": "guard-release / check-release-branch-name"
}
]
}
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/guard-release-branch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Source-repo caller wrapper for the reusable guard-release-branch workflow.
# Copy to .github/workflows/guard-release-branch.yml in repos using the
# forever-dev + release/* flow.
#
# Rejects PRs to main whose head branch doesn't start with `release/`.
# Keeps `dev` off the list of PR heads, which is what makes
# `deleteBranchOnMerge: true` safe to leave on without risking `origin/dev`.
#
# Default prefix `release/` is supplied by the reusable workflow; pass
# `with: prefix: <other>` to override.
#
# Required caller permissions: pull-requests: read
#
# The caller's job key must be `guard-release:` so the required status
# check context is `guard-release / check-release-branch-name`.
name: Guard release branch pattern

on:
pull_request:
branches: [main]

permissions:
pull-requests: read

jobs:
guard-release:
uses: brettdavies/.github/.github/workflows/guard-release-branch.yml@main
7 changes: 2 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Source repo release wrapper — calls the centralized reusable workflow.
# Copy to .github/workflows/release.yml in the tool repo.
#
# Template parameters:
# agentnative -- crate name (e.g., xurl-rs, bird)
# agentnative -- binary name (e.g., xr, bird)
# crate: agentnative (crates.io name) | bin: anc (installed executable)
#
# Pipeline: check-version -> build (5 targets) -> crates.io -> draft release -> homebrew
name: Release
Expand All @@ -22,6 +19,6 @@ jobs:
uses: brettdavies/.github/.github/workflows/rust-release.yml@main
with:
crate: agentnative
bin: agentnative
bin: anc
secrets:
CI_RELEASE_TOKEN: ${{ secrets.CI_RELEASE_TOKEN }}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/target
/dist
*.pdb
.env
.env.local
*.local
85 changes: 85 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Global markdownlint-cli2 configuration
# Canonical version: 2026.04.15
# Symlinked to ~/.markdownlint-cli2.yaml via stow
#
# Per-repo copies should preserve the `Canonical version` line above and bump it on resync;
# a stale calver compared to this file is the signal that the per-repo copy has drifted.
#
# Documentation: https://github.com/DavidAnson/markdownlint-cli2
# Rules: https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md

# Configure markdownlint rules
config:
# Use all default rules
default: true

# MD003: Heading style - use ATX style (#)
MD003:
style: "atx"

# MD004: Unordered list style - use dashes
MD004:
style: "dash"

# MD007: Unordered list indentation - 2 spaces
MD007:
indent: 2

# MD009: Trailing spaces - allow 2 spaces for line breaks
MD009:
br_spaces: 2

# MD013: Line length - 120 chars (more reasonable for code docs)
MD013:
line_length: 120
code_blocks: false # Don't check code blocks
tables: false # Don't check tables
headings: false # Don't check headings

# MD024: Allow duplicate headings in different sections
MD024:
siblings_only: true

# MD025: Single top-level heading - allow multiple (for changelogs, etc.)
MD025: false

# MD033: Allow inline HTML for specific elements
MD033:
allowed_elements:
- "br"
- "img"
- "a"
- "details"
- "summary"
- "sub"
- "sup"
- "kbd"

# MD034: Bare URLs - allow (common in docs)
MD034: false

# MD036: Emphasis used as heading - allow (stylistic choice)
MD036: false

# MD041: First line should be top-level heading - disable (not always needed)
MD041: false

# MD046: Code block style - fenced
MD046:
style: "fenced"

# MD048: Code fence style - backticks
MD048:
style: "backtick"

# Ignore patterns
ignores:
- "node_modules/**"
- "**/node_modules/**"
- "vendor/**"
- "target/**" # Rust build artifacts; harmless for non-Rust projects
- ".git/**"
- "*.min.md"

# Fix automatically when --fix is used
fix: true
94 changes: 94 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# AGENTS.md

## Running anc

The crate is `agentnative`. The installed binary is `anc`.

```bash
# Check current project — `check` is implicit when the first non-flag arg is a path
anc .

# Resolve a command on PATH and run behavioral checks against it
anc --command ripgrep

# JSON output for parsing
anc . --output json

# Quiet mode (warnings and failures only)
anc . -q

# Filter by principle (1-7)
anc . --principle 4

# Behavioral checks only (no source analysis)
anc . --binary

# Source checks only (no binary execution)
anc . --source
```

Bare `anc` (no arguments) prints help and exits 2. This is a non-negotiable fork-bomb guard: when agentnative dogfoods
itself, children spawned without arguments must not recurse into `check .`.

## Exit Codes

- `0` — all checks passed
- `1` — warnings present, no failures
- `2` — failures, errors, or usage errors (bare `anc`, unknown flag, mutually exclusive flags, command not found on
PATH)

Exit 2 is overloaded. To distinguish "ran but found problems" from "called
incorrectly", parse stderr — usage errors include `Usage:` text; check failures don't.

## Project Structure

- `src/check.rs` — Check trait definition
- `src/checks/behavioral/` — checks that run the compiled binary
- `src/checks/source/rust/` — ast-grep source analysis checks
- `src/checks/project/` — file and manifest inspection checks
- `src/runner.rs` — binary execution with timeout and caching
- `src/project.rs` — project discovery and source file walking
- `src/scorecard.rs` — output formatting (text and JSON)
- `src/types.rs` — CheckResult, CheckStatus, CheckGroup, CheckLayer

## Adding a New Check

1. Create a file in the appropriate `src/checks/` subdirectory
2. Implement the `Check` trait: `id()`, `group()`, `layer()`, `applicable()`, `run()`
3. Register in the layer's `mod.rs` (e.g., `all_rust_checks()`)
4. Add inline `#[cfg(test)]` tests

## Testing

```bash
cargo test # unit + integration tests
cargo test -- --ignored # fixture tests (slower)
```

## Spec source (principles)

The canonical specification of the 7 agent-readiness principles lives in the vault, one file per principle. The `anc`
checks in `src/checks/` are derived **manually** from these files — there is no build-time import, no live link. When a
principle's spec changes, propagate to the relevant check(s) deliberately.

- `~/obsidian-vault/Projects/brettdavies-agentnative/principles/index.md` — table of P1-P7 with status (draft /
under-review / locked).
- `~/obsidian-vault/Projects/brettdavies-agentnative/principles/AGENTS.md` — iteration workflow, pressure-test protocol,
per-file structure. Read before proposing a new check that stretches the existing P<n> coverage.

When a check is added or revised, its code or doc comment should name the principle code (`P<n>`) it implements for
traceability. Do not embed the principle text in the check source.

## External signal / research

Curated external signal that informs principle iteration, check rules, and positioning lives in the sibling research
folder:

- `~/obsidian-vault/Projects/brettdavies-agentnative/research/index.md` — top of the research tree. Lists every extract
with date, topic, and which principles it maps to. Read this before adding new checks driven by external patterns or
competitor behavior.
- `extracts/` — curated, topic-scoped files (verbatim quotes, principle mapping, recommended uses).
- `raw/` — full-text captures.

When an extract names concrete linter-rule candidates, walk its **"Linter rule coverage audit"** or equivalent
section against existing checks in `src/checks/` before opening a new check.
Loading