Skip to main content
Glama

Aegis Guardrails: project rules for Claude Code, Codex CLI and Antigravity

PyPI Python License: Apache 2.0 Runtime dependencies: 0 CI

Aegis gives Claude Code, Codex CLI and Antigravity the project rules for the files they are about to edit, then checks the result with aegis check in a git pre-commit hook and in CI. It is a Model Context Protocol (MCP) server (aegis-mcp) plus a CLI (aegis), with zero runtime dependencies.

Rules are short markdown files in .aegis/rules/, committed with your code. Aegis serves the rules that match each file before the agent edits it, checks forbidden patterns at commit and in CI, and records evidence for human review. An instructions file alone depends on the agent remembering it; Aegis adds checks for the parts you can express as code patterns.

In one coding session, 749 of 1,339 agent steps were rework. That single-developer observation motivated Aegis; it is not a measured productivity gain. See Why Aegis is built this way for the evidence and its limits.

Quick start

Aegis runs a 3-step loop in any git repository with Python 3.9 or newer:

  1. Step 1 — Install & initialize: Install aegis-guardrails (pipx install aegis-guardrails or pip install aegis-guardrails) and run aegis init in your repo to write the AGENTS.md bootstrap, register aegis-mcp with your hosts, and install the pre-commit hook.

  2. Step 2 — Scan before edit: Your coding agent calls aegis_scan over MCP before editing files to receive just-in-time rules matched to those paths.

  3. Step 3 — Block bad commits in Git & CI: aegis check runs automatically in the pre-commit hook and in CI to block forbidden AST patterns and, with aegis check --ci, rule weakenings.

pipx install aegis-guardrails            # or: pip install aegis-guardrails
cd my-app
aegis init --host claude-code,codex-cli   # or --host auto: every supported host found on this machine

If pip stops with externally-managed-environment (PEP 668, as many Linux distributions and Homebrew Python do), run pipx install aegis-guardrails or install into a virtual environment. If your shell then says aegis: command not found, run pipx ensurepath after a pipx install, activate the virtual environment, or run the script by its full path (on Linux ~/.local/bin/aegis after pip install --user); aegis init and aegis doctor print the PATH fix for your shell. Do not fall back to python3 -m aegis_cli inside a repository: -m imports from the current directory first.

aegis init prints its plan and asks before writing. It preserves your text outside its marked AGENTS.md block. The standard preset adds five advisory starter personas; set their target_paths to activate them.

init seeds one rule that is active from day one: .aegis/rules/invariants/no-eval.md (leave it out with --rules none-active). Because builtin: true is set on its call predicates, it catches Python's builtin eval() and exec() while allowing method calls like pandas df.eval(), PyTorch model.eval(), and SQLModel session.exec(). Here is what it looks like, as a template for your own (aegis rule create writes one for you):

---
id: no-eval
type: invariant
domain: security
enforcement: gate
hypothesis: Agents reach for eval() to parse input
target_paths:
  - "**/*.py"
forbid_ast:
  calls:
    - name: eval
      builtin: true
    - name: exec
      builtin: true
---
Never call `eval` or `exec` on data. Parse it with `json.loads` or `ast.literal_eval`.

aegis check enforces the reviewed rules: a rule is enforced locally once it is in the base (committed, when there is no origin/HEAD; on the branch origin/HEAD points to, when there is one). Commit .aegis/ and AGENTS.md before you try it (.aegis/state/ is git-ignored, and the outcome ledger lives in your git directory, outside the working tree):

git add .aegis AGENTS.md && git commit -m "Add Aegis"

An agent that calls aegis_scan before editing app.py gets this rule (aegis scan app.py shows the same thing in a shell). If the change calls eval anyway, the check fails, and so does git commit, because the pre-commit hook runs the same check on the staged content. With no file arguments, aegis check looks only at tracked files: your changes and staged files (on a clean tree, what the branch adds to its base). It skips untracked files, so git add a new file first, or name it: aegis check app.py.

$ git add app.py
$ aegis check
checkpoint: all checks passed
🔴 forbid_ast:no-eval: app.py — Forbidden call 'eval' matched rule forbid_ast.calls
Layer 1: 1/3 FAILED — forbid_ast:no-eval

checkpoint: all checks passed comes from a repository-wide hygiene scan (a test file for each source file, hard-coded paths, rule conventions) that warns unless you pass --strict; a gate or invariant rule that does not use enforcement: gate and a rule file that cannot be loaded always fail. The FAILED line is Layer 1's verdict, which includes the checkpoint, and it sets the exit code.

Run aegis doctor to check registrations. git commit --no-verify skips the local hook, so also run the checks in CI. aegis init --ci writes .github/workflows/aegis.yml, pinned to the Aegis version that generated it: its check job runs aegis check and aegis check --ci with contents: read, pull-requests: read and GH_TOKEN. Make that job required. See CI governance for base-branch review and test-credit setup.

Related MCP server: SpecLock

Works with your agents

Host

Setup

Status

Claude Code

aegis init --host claude-code

User-scope MCP; AGENTS.md, or an @AGENTS.md block in an existing CLAUDE.md

Codex CLI

aegis init --host codex-cli

User-scope MCP and AGENTS.md

Antigravity (app, IDE and agy)

aegis init --host antigravity

Config-file MCP; run init once per repo on each machine because the host sends no workspace

Kiro, Cursor, GitHub Copilot, Windsurf

aegis init --host kiro,cursor,copilot,windsurf

Experimental registrations; not checked on real installs; no Aegis pre-tool hooks

Gemini CLI

Retired; aegis init --host gemini-cli exits 2

Use Antigravity (--host antigravity) instead

--host auto discovers supported hosts from CLIs, config directories and app bundles. CLI, IDE and desktop surfaces share registrations where the host supports them. See Hosts and hooks for file paths, instruction limits, platform gaps and safe repair.

How it works

  1. Bootstrap. aegis init writes a small AGENTS.md block and registers the MCP server.

  2. Scan. The agent calls aegis_scan with the paths it will edit. Mandatory rules come from the reviewed base; the response lists omitted mandatory rules too.

  3. Edit and verify. Run the project's checks. An optional aegis check --record --tests records an isolated test run for the exact git tree. If the scan returned rule IDs, the agent can report them with aegis_report_outcome; if none matched, skip that report. Never invent IDs.

  4. Commit and review. The hook checks staged content; CI checks the commit and governance changes. Optional Layer 2 model review is advisory.

  5. Review the evidence. aegis sync derives fitness and suggests lifecycle changes. A person reviews and applies them; Aegis never promotes rules automatically.

Passing a check, recording a test run and earning CI-confirmed rule credit are separate results. Automatic test runs retain complete per-language evidence; an explicit global test command takes precedence and needs complete JUnit for a receipt. Test pairing alone is not execution evidence. See Evidence and outcomes.

Read How Aegis works for the concepts and examples, or Architecture for components and data flow.

What's included

  • A CLI with 15 commands (init, uninstall, doctor, migrate, check, approve, scan, status, rule, sync, hook, team, skills, benchmark, package) and an MCP server with 5 tools (aegis_scan, aegis_report_outcome, aegis_create_rule, aegis_list_rules, aegis_capture_insight).

  • 12 starter rules: grounding claims in code, dry runs before destructive commands, behavioral tests, TDD, git hygiene and more (aegis init --rules minimal|standard|full seeds 2, 5 or all 12; set target_paths to activate them).

  • 15 skills: SKILL.md playbooks synced by aegis skills sync (or aegis init --skills) into .claude/skills/ and .agents/skills/.

  • Built-in security checks: language security packs and a known-format secret scan check what your change introduces; explicit allow comments record suppressions.

  • A Python SDK facade, aegis_sdk.Governance, for tools that query rules and fitness.

Language

Parsing

Security rules

Regression tests (fail-to-pass)

Coverage

Test pairing

Python

In process

7

pytest

coverage.py

Filename lookup

TS/JS

In process, default on

5

User JUnit runner

User LCOV command

.test / .spec, test directories

Go

Opt-in cached parser

4

go test -json

Go coverprofile

Same package

Rust

In process, default on

2

Cargo integration targets

User LCOV command

Inline / integration

Go parsing needs Go ≥1.21. JS/TS and Rust parsing need no Node or Rust toolchain; executing their tests needs installed tools and dependencies. See Language checks for extraction limits, configuration, unavailable evidence and receipt requirements.

Agent teams

When parallel agents work in separate worktrees (lanes), declare each lane's path scope with aegis team claim docs --paths 'docs/**' README.md. A lease is cooperative conflict input — not a lock, not an identity, and not proof an agent is still running — and overlapping live claims are refused.

Verify containment with aegis check --lane docs: every path changed since the merge base must stay inside the lane's scope, and no Python test may disappear or gain a skip. With a lease or --paths the check is self-attested; with --base-policy it reads .aegis/team.json from the base branch and is witnessed. In CI it is advisory (not a required check). See Agent teams for lease refs and aegis team metrics.

Limits and trust

Aegis checks explicit patterns; a rule written only as prose remains guidance. AST matching is syntactic, not a proof about runtime behavior. Missing driver coverage is reported as unverified no_driver; ordinary --strict makes it blocking. Native files over 2 MiB produce advisory too_large evidence, and active parser failures fail closed.

aegis doctor reports four enforcement tiers:

Tier

Mechanism

Limit

Advisory

AGENTS.md bootstrap, MCP instructions, JIT rules

The agent can ignore guidance

Best-effort

per-host pre-tool hooks

Fail open on Aegis errors; shell edits bypass edit checks; host support varies

Local floor

git pre-commit runs aegis check --hook (--no-verify bypasses it)

The committer can skip the hook

Authoritative

CI runs aegis check on the exact SHA; a human merges

Depends on protected checks and review of governance and workflow changes

Plain aegis check enforces reviewed rules where origin/HEAD resolves: a pull request that deletes a rule and breaks it fails plain check there. Without that ref, as in CI's checkout, plain check enforces the pull request's own rules and aegis check --ci is what catches a deleted or weakened rule. Make both checks required.

The trust tiers describe protection of the rules themselves: C is self-attested, B uses an SSH approval key the agent cannot use, and A adds an independent code-owner review. With no key in the base's allowed_signers, governance-file changes pass with a note; rule weakening still fails unless a qualifying Tier A review approves it. Tier B holds only while the pull request leaves Aegis and .github/workflows/** alone. aegis doctor --github shows the setup without changing it. See Trust tiers.

Aegis does not sandbox processes or authenticate its mutable local ledger. CI-confirmed checks and detector replay inform fitness, but promotion requires reviewed human labels and sufficient breadth. Evidence and outcomes explains the thresholds and remaining limits.

FAQ

How do I add guardrails to Claude Code? Run aegis init --host claude-code in the repo. It registers the server at user scope and writes the AGENTS.md bootstrap (or adds @AGENTS.md to an existing CLAUDE.md). Run aegis hook install --host claude-code to add the pre-tool hook.

How do I add guardrails to Codex CLI? Run aegis init --host codex-cli. For the pre-tool hook, run aegis hook install --host codex-cli and trust the hook in Codex's /hooks screen.

Claude Code ignoring CLAUDE.md? A CLAUDE.md is advice in the model's context, and nothing checks that Claude Code followed it. Claude Code reads AGENTS.md only when the repository has no CLAUDE.md, so aegis init adds an @AGENTS.md block to an existing one (aegis doctor flags a CLAUDE.md that shadows AGENTS.md). Aegis then puts the matching rules in front of the agent when it edits, the pre-tool hook (aegis hook install --host claude-code) blocks unscanned edits and destructive commands (it fails open on any Aegis error and does not see edits made through shell commands), and aegis check blocks banned patterns at commit and in CI.

How do I enforce AGENTS.md rules? An AGENTS.md is read by the agent, not enforced. Keep it short and put every rule a forbid_ast pattern can express into .aegis/rules/, like the no-eval example above: aegis check then fails the commit and the CI run, and a required aegis check --ci fails a pull request that weakens the rule. A rule without forbid_ast stays guidance that aegis_scan serves to the agent.

What is AGENTS.md? A markdown instructions file in the repository root that coding agents (Codex CLI, Antigravity, Claude Code) read at session start. Aegis writes only a small bootstrap block into it; rules stay in .aegis/rules/ and are served just-in-time via aegis_scan.

Does Aegis send my code anywhere? Not by itself. Aegis opens no network connection of its own, and the ledger stays on your machine, in your git directory. Programs you authorize can reach the network: aegis check --full --llm-cmd ... sends your plan, changed non-test Python source, test output and Layer 1 results to your model command; test, coverage, perf and custom-driver commands can run code with network access; the commands listed in PRIVACY.md run your own gh; and aegis sync --pr pushes one branch to your remote. Your agent host sends what Aegis returns to its own model provider.

I used Aegis 3.x. How do I upgrade? Run aegis migrate, then aegis migrate --apply, aegis init --host <your hosts>, and aegis doctor --fix. See the changelog for details.

Documentation, contributing, security, license

Apache 2.0. Copyright 2026 Nicholas Seney. See LICENSE and NOTICE.

Available Tools

5 tools
aegis_capture_insightA

Appends a user correction or preference to ~/.aegis/insights/ for rule curation; use aegis_report_outcome to report whether rules helped. Secrets are redacted, quote is cut to 300 characters and paths default to the dirty git paths. Agent captures stay at level: 'suggestion': invisible to aegis_scan, never counted by aegis rule insight review, never upgraded. Capped at 50 captures per session and rate-limited to 5 calls per 60 seconds.

NameRequiredDescriptionDefault
pathsNoPaths it applies to (psrc 'explicit'; at most 20 of 512 chars); default: up to 20 dirty git paths (psrc 'dirty').
quoteYesThe user's verbatim correction (1-1024 chars); secrets are redacted and 300 chars stored.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite only carrying readOnlyHint=false, the description discloses the behaviors an agent actually needs: secret redaction, 300-char quote truncation, dirty-git-path defaults, suggestion-level invisibility to aegis_scan and rule review, no upgrading, a 50-per-session cap and 5-per-60s rate limit. This is a mutation tool and the side effects and limits are fully spelled out.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action and the primary alternative in the first clause, and every subsequent clause carries a distinct fact (redaction, truncation, level, rate limits) rather than filler. It is dense and semicolon-packed, which slightly taxes scanning, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter mutation tool with no output schema and minimal annotations, the description covers persistence location, side effects, visibility, caps, and rate limits. Nothing an agent needs in order to call it safely and correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline is 3, but the description adds meaning beyond the schema: it clarifies that a 1024-char quote is truncated to 300 stored characters, and confirms the dirty-git-path default for paths. This meaningfully complements rather than repeats the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (appends) and resource (user correction or preference written to ~/.aegis/insights/ for rule curation), and explicitly distinguishes itself from the sibling aegis_report_outcome. An agent can tell exactly which tool to pick without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use this to capture a correction/preference, use aegis_report_outcome to report whether rules helped. That is a concrete alternative with a selection condition. It lacks an explicit 'do not use when' clause, keeping it just under a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aegis_create_ruleA
Read-onlyIdempotent

Builds a prompt for drafting a rule from description, with up to three active workspace rules (500 chars each) as examples; it writes nothing to disk. Save the result to .aegis/rules/<type_dir>/<id>.md as instruction says. Check aegis_list_rules for an existing rule first.

NameRequiredDescriptionDefault
domainNoDomain hint for the draft prompt (security, correctness, efficiency, style, governance).
rule_typeNoRule type, passed to the draft prompt as a hint.
descriptionYesThe defect, anti-pattern or invariant the rule should codify.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false, and the description reinforces this counterintuitively ('it writes nothing to disk'), which is genuinely useful given the `create_rule` name implies a write. It also discloses the backtracking behavior of pulling in 'up to three active workspace rules (500 chars each) as examples' and assigns the actual file write to the agent, split responsibilities the annotations alone would not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each carrying distinct information: what it produces, the no-disk-write caveat, and the save/check workflow. The npm package name and path templates make the middle portion dense, but nothing is redundant; the key point that it merely builds a prompt is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter, non-mutating tool with 100% schema coverage and no output schema, the description covers the essentials: input basis, example-injection behavior, and the manual save step. The one gap is what the returned 'instruction' actually contains, but the reference to `instruction` in the save step gives the agent enough to act.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description exceeds that by explaining how parameters shape the output — the example budget of three rules at 500 chars each and the fact that `domain` and `rule_type` are hints fed into the draft prompt — which the schema only labels generically.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it 'builds a prompt for drafting a rule' from the `description` parameter, and explicitly clarifies it writes nothing to disk despite the name `create_rule`. It does not directly contrast itself with `aegis_capture_insight` or `aegis_scan`, but the prompt-building framing is distinct enough to separate it from the other siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit precondition — 'Check `aegis_list_rules` for an existing rule first' — naming the sibling that should be consulted, and describes the follow-up step of saving the result to `.aegis/rules/<type_dir>/<id>.md`. What's missing is guidance on when this tool is inappropriate or how it differs from `aegis_capture_insight`, which also produces rule-like content.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aegis_list_rulesA
Read-onlyIdempotent

Lists every rule with metadata and ledger fitness (_error if unloadable, _expired: true if retired), the stale_rules edited since the last aegis sync, and non-rule files under .aegis/rules/ (ignored). Records no scan or exposure: call aegis_scan before editing files.

NameRequiredDescriptionDefault
viewNo'full' (default), 'summary' (key fields, lists capped at 10 plus <list>_count) or 'ids'.
rule_typeNoOnly rules and stale_rules of this type.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds useful context about sentinel fields (`_error` for unloadable rules, `_expired: true` for retired ones) and the existence of stale_rules and ignored files. However, it doesn't state anything about pagination, capping, or ordering beyond what the schema's view description hints at. With annotations covering safety, a 3 is fair; the added context about return shape nudges the score up.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense sentence packs purpose, three output categories, and a prerequisite call, front-loading the main verb. It is slightly over-packed with parentheticals, which impacts readability, but every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description must convey the return shape. It covers the main fields (metadata, fitness, stale_rules, ignored) and sentinel values, which is sufficient for an agent to anticipate the response. Minor gap: the view mode implications (capping at 10, ids) are left to the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema describes both parameters at 100% coverage, so the description doesn't need to repeat their semantics. It does add conceptual context by mentioning stale_rules inline, which helps the agent understand what rule_type filters against. Baseline 3 is appropriate when the schema carries the parameter documentation burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Lists) and resource (rules) plus scope: metadata, ledger fitness flags, stale rules, and ignored non-rule files. This is distinguishable from the siblings aegis_scan, aegis_create_rule, aegis_report_outcome, and aegis_capture_insight, none of which are list operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly warns that this tool records no scan or exposure and directs the agent to call aegis_scan before editing files, naming the alternative. It does not, however, explain when to prefer one list view over another, leaving that to the schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aegis_report_outcomeA

Call after verifying a change with tests or aegis check, naming rules from aegis_scan; use aegis_capture_insight for user corrections. With a passing aegis check --record --tests row for the current tree, the rules this session's scans exposed that match the diff are credited, counting once CI passes on the landing commit; without one, it writes at most one unwitnessed claim per session and tree, which earns no credit. Capped at 200 report rows per session and rate-limited to 5 calls per 60 seconds.

NameRequiredDescriptionDefault
viewNo'full' (default), 'summary' (key fields, lists capped at 10 plus <list>_count) or 'ids'.
filesNoPaths edited in this change, for scan-before-edit compliance only (at most one 'edit' event per report); never affects credit.
notesNoAccepted for compatibility; ignored, never stored.
outcomeYes'success', 'tp' and 'pass' claim a true positive (credited only after CI); the others read as a neutral trigger, never a false positive.
rules_usedYesRule IDs from aegis_scan; credit comes from this session's scan exposure and the diff, not this list.
rework_countNoAccepted for compatibility; ignored, never stored.
tests_passedNoAccepted for compatibility; ignored, never stored.
idempotency_keyYesUnique per report (scoped by host and session): a retry is a no-op; reuse with another outcome fails.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only readOnlyHint=false, so the description carries the burden and does it well: it discloses credit vs. no-credit mechanics, the one-unwitnessed-claim-per-session/tree limit, the 200-row session cap, the 5-per-60-second rate limit, and the CI-passing condition for credit. These are exactly the operational constraints an agent needs before invoking a stateful reporting tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the calling condition and the sibling routing, followed by the credit and cap mechanics. The second sentence is dense but every clause (credit condition, no-credit fallback, row cap, rate limit) carries required information, so there is little waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter, stateful reporting tool with no output schema and minimal annotations, the description covers invocation timing, credit rules, fallback behavior, idempotency implications via retry semantics in schema, caps, and rate limits. Nothing material is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter including the outcome enum's credit semantics, files' non-effect on credit, and the ignored compatibility fields. The description reinforces that credit derives from session scan exposure and the diff rather than the `rules_used` list, but adds little per-parameter guidance (e.g. `view`) beyond what the schema states; baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description makes clear this records a change outcome for credit (calling it after tests or `aegis check`, naming rules from `aegis_scan`) and explicitly contrasts it with `aegis_capture_insight` for user corrections. The core verb 'report the outcome of verified work' is implied through the calling conditions rather than stated outright, so it falls short of a perfect 5 but is easily distinguishable from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit preconditions ('call after verifying a change with tests or `aegis check`'), names the alternative for the adjacent case (`aegis_capture_insight` for user corrections), and spells out the two branches — credited with a passing recorded check row, or a single unwitnessed no-credit claim per session and tree.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aegis_scanA
Read-onlyIdempotent

Call before editing files: returns the rules for files (default: the git diff), ranked by fitness within the token budget, and records this session's scan and rule exposure. Mandatory rules (gates, invariants) take at most two slots (the excess is in omitted_mandatory) and are served from the reviewed base, so branch-local edits to them do not bind and are listed in unreviewed_rules. Use aegis_list_rules to browse without recording and aegis_report_outcome after verifying. Fails closed if a rule file cannot be loaded.

NameRequiredDescriptionDefault
viewNo'full' (default), 'summary' (key fields, lists capped at 10 plus <list>_count) or 'ids'.
filesNoPaths you are about to edit; omitted or empty means the files changed in the git work tree and index.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations by disclosing the two-slot cap on mandatory rules, the `omitted_mandatory` overflow field, the reviewed-base binding rule with `unreviewed_rules`, and fail-closed behavior on load errors. It also discloses the session-recording side effect, which is worth noting against readOnlyHint but reads as internal telemetry rather than a mutation of domain data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Effectively front-loaded: the trigger condition and core behavior come first, then edge cases and routing. It is a single dense paragraph with backticked field names, and every clause carries information, though the flow is slightly overpacked.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description still names the key return fields (`omitted_mandatory`, `unreviewed_rules`) and the failure mode. For a two-parameter read tool with full schema coverage, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are fully documented there, including the `files` default and the `view` enum. The description only restates the `files` default and adds nothing about `view` modes or path format, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: returns the rules applicable to `files`, ranked by fitness within a token budget, and defaults to the git diff. It explicitly contrasts with the sibling `aegis_list_rules` ("browse without recording"), so an agent can distinguish the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Opens with a directive ("Call before editing files") and names both alternatives plus their selecting conditions: `aegis_list_rules` when you want to browse without recording, `aegis_report_outcome` after verifying. When-to-use and when-not-to-use are both explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv4.4.0
    • Changedaegis_capture_insight5 fields changed
      • changedInput schema / properties / paths / description
        Previous value: -"Optional workspace-relative file paths this correction applies to (sets psrc='explicit'). When omitted or empty, defaults to currently modified git worktree paths (psrc='dirty')."New value: +"Paths it applies to (psrc 'explicit'; at most 20 of 512 chars); default: up to 20 dirty git paths (psrc 'dirty')."
      • addedInput schema / properties / paths / items / maxLength
        Added value: +512
      • addedInput schema / properties / paths / maxItems
        Added value: +20
      • changedInput schema / properties / quote / description
        Previous value: -"Non-empty verbatim quote of the user's correction or preference (1-1024 chars; secrets are automatically redacted and stored text is capped at 300 chars)."New value: +"The user's verbatim correction (1-1024 chars); secrets are redacted and 300 chars stored."
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "error": {
        -      "description": "Error message when status='FAIL'.",
        -      "type": "string"
        -    },
        -    "id": {
        -      "description": "Content-addressed insight identifier ('ins-<12-hex>').",
        -      "type": "string"
        -    },
        -    "level": {
        -      "description": "Corroboration tier: 'suggestion' initially, or 'W2' when matched to a hook-captured user prompt in the same session.",
        -      "enum": [
        -        "suggestion",
        -        "W2"
        -      ],
        -      "type": "string"
        -    },
        -    "paths": {
        -      "description": "Workspace-relative file paths associated with this insight.",
        -      "items": {
        -        "type": "string"
        -      },
        -      "type": "array"
        -    },
        -    "psrc": {
        -      "description": "Path provenance: 'explicit' when caller supplied paths, or 'dirty' when inferred from git status.",
        -      "enum": [
        -        "explicit",
        -        "dirty"
        -      ],
        -      "type": "string"
        -    },
        -    "status": {
        -      "description": "'OK' when the insight row was appended, or 'FAIL' on validation/storage error.",
        -      "enum": [
        -        "OK",
        -        "FAIL"
        -      ],
        -      "type": "string"
        -    },
        -    "text": {
        -      "description": "Secret-redacted and length-capped (max 300 chars) correction quote stored in the ledger.",
        -      "type": "string"
        -    }
        -  },
        -  "required": [
        -    "status",
        -    "id",
        -    "level",
        -    "text",
        -    "paths",
        -    "psrc"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changedaegis_create_rule4 fields changed
      • changedInput schema / properties / description / description
        Previous value: -"Non-empty natural-language description of the engineering defect, anti-pattern, or invariant to codify into a rule."New value: +"The defect, anti-pattern or invariant the rule should codify."
      • changedInput schema / properties / domain / description
        Previous value: -"Optional domain hint injected into the drafting prompt (e.g., 'security', 'correctness', 'efficiency', 'style', 'governance')."New value: +"Domain hint for the draft prompt (security, correctness, efficiency, style, governance)."
      • changedInput schema / properties / rule_type / description
        Previous value: -"Optional target rule category ('invariant' or 'gate' for blocking checks; 'trap', 'boundary', 'persona', or 'contract' for advisory guidance). Determines the target subdirectory under .aegis/rules/."New value: +"Rule type, passed to the draft prompt as a hint."
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "error": {
        -      "description": "Error message when status='FAIL'.",
        -      "type": "string"
        -    },
        -    "instruction": {
        -      "description": "Step-by-step instruction telling the caller where under .aegis/rules/<type_dir>/<id>.md to save the drafted markdown.",
        -      "type": "string"
        -    },
        -    "prompt": {
        -      "description": "Structured rule-generation prompt containing schema requirements and up to three workspace rule examples.",
        -      "type": "string"
        -    },
        -    "status": {
        -      "description": "Present with value 'FAIL' only when input validation fails.",
        -      "type": "string"
        -    }
        -  },
        -  "required": [
        -    "prompt",
        -    "instruction"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changedaegis_list_rules3 fields changed
      • changedInput schema / properties / rule_type / description
        Previous value: -"Optional filter restricting both 'rules' and 'stale_rules' to a single rule category ('invariant', 'trap', 'gate', 'boundary', 'persona', or 'contract'). Omit to list all categories."New value: +"Only rules and stale_rules of this type."
      • changedInput schema / properties / view / description
        Previous value: -"Optional response projection: 'full' (default, complete payload), 'summary' (retains identity/type/status/fitness fields, caps lists at 10 items, and adds <list>_count), or 'ids' (projects each list to rule ID strings). Error responses are never projected."New value: +"'full' (default), 'summary' (key fields, lists capped at 10 plus <list>_count) or 'ids'."
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "error": {
        -      "description": "Error message when status='FAIL'.",
        -      "type": "string"
        -    },
        -    "ignored": {
        -      "description": "Non-rule markdown files under .aegis/rules/ with path and reason.",
        -      "type": "array"
        -    },
        -    "ignored_count": {
        -      "description": "Total count of ignored files before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "rules": {
        -      "description": "Workspace rule records with metadata and ledger fitness (or rule ID strings when view='ids').",
        -      "type": "array"
        -    },
        -    "rules_count": {
        -      "description": "Total count of rules before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "stale_rules": {
        -      "description": "Rules edited since the last 'aegis sync' derived-file regeneration.",
        -      "type": "array"
        -    },
        -    "stale_rules_count": {
        -      "description": "Total count of stale_rules before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "status": {
        -      "description": "Present with value 'FAIL' only when the rules directory cannot be safely loaded.",
        -      "type": "string"
        -    }
        -  },
        -  "required": [
        -    "rules",
        -    "stale_rules",
        -    "ignored"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changedaegis_report_outcome9 fields changed
      • changedInput schema / properties / files / description
        Previous value: -"Optional workspace-relative file paths edited in this change. Records one 'edit' activity event per idempotency_key for scan-before-edit compliance (aegis status --compliance); does not affect rule credit."New value: +"Paths edited in this change, for scan-before-edit compliance only (at most one 'edit' event per report); never affects credit."
      • changedInput schema / properties / idempotency_key / description
        Previous value: -"Caller-supplied unique key (1-256 chars, scoped per host and session). Retrying with the same key and outcome is a no-op; reusing a key with a different outcome fails with status 'FAIL'."New value: +"Unique per report (scoped by host and session): a retry is a no-op; reuse with another outcome fails."
      • changedInput schema / properties / notes / description
        Previous value: -"Optional free-text context describing how the rules helped or failed (max 4096 chars)."New value: +"Accepted for compatibility; ignored, never stored."
      • changedInput schema / properties / outcome / description
        Previous value: -"Verification result for the rules in this change: 'success'/'tp'/'pass' record a true positive ('tp'), 'failure'/'fp'/'fail' record a false positive ('fp'), and 'partial' records a neutral trigger ('trigger')."New value: +"'success', 'tp' and 'pass' claim a true positive (credited only after CI); the others read as a neutral trigger, never a false positive."
      • changedInput schema / properties / rework_count / description
        Previous value: -"Optional non-negative integer count of edit-and-retest cycles before verification succeeded (default: 0)."New value: +"Accepted for compatibility; ignored, never stored."
      • changedInput schema / properties / rules_used / description
        Previous value: -"Non-empty list of existing rule IDs from aegis_scan. Validated against the workspace rule inventory; actual fitness credit is computed server-side from session scan exposure and git diff paths."New value: +"Rule IDs from aegis_scan; credit comes from this session's scan exposure and the diff, not this list."
      • changedInput schema / properties / tests_passed / description
        Previous value: -"Optional boolean recording whether the project's test suite passed during verification."New value: +"Accepted for compatibility; ignored, never stored."
      • changedInput schema / properties / view / description
        Previous value: -"Optional response projection: 'full' (default, complete payload), 'summary' (retains identity/type/status/fitness fields, caps lists at 10 items, and adds <list>_count), or 'ids' (projects each list to rule ID strings). Error responses are never projected."New value: +"'full' (default), 'summary' (key fields, lists capped at 10 plus <list>_count) or 'ids'."
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "aegis_version": {
        -      "description": "Running Aegis package version string.",
        -      "type": "string"
        -    },
        -    "check": {
        -      "description": "Check record ID that witnessed the report (present when status='recorded').",
        -      "type": "string"
        -    },
        -    "checked_at": {
        -      "description": "UTC ISO-8601 timestamp when the report was processed.",
        -      "type": "string"
        -    },
        -    "credited": {
        -      "description": "Rule IDs credited in the outcome ledger (empty for unwitnessed 'claimed' or 'rate_limited' reports).",
        -      "items": {
        -        "type": "string"
        -      },
        -      "type": "array"
        -    },
        -    "credited_count": {
        -      "description": "Total count of credited rules before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "error": {
        -      "description": "Error message when status='FAIL'.",
        -      "type": "string"
        -    },
        -    "limit": {
        -      "description": "Per-session report cap (200) returned when status='rate_limited'.",
        -      "type": "integer"
        -    },
        -    "recorded": {
        -      "description": "False when status='rate_limited' or when an unwitnessed claim for the same session and tree was already recorded.",
        -      "type": "boolean"
        -    },
        -    "scope": {
        -      "description": "Workspace scope metadata envelope ({tree}).",
        -      "type": "object"
        -    },
        -    "source": {
        -      "description": "Command or tool name that produced the response ('aegis_report_outcome').",
        -      "type": "string"
        -    },
        -    "status": {
        -      "description": "Report disposition: 'recorded' (witnessed by a matching check record), 'claimed' (unwitnessed self-report), 'rate_limited' (session cap reached), or 'FAIL'.",
        -      "enum": [
        -        "recorded",
        -        "claimed",
        -        "rate_limited",
        -        "FAIL"
        -      ],
        -      "type": "string"
        -    },
        -    "tree": {
        -      "description": "Git tree hash computed for the workspace at report time.",
        -      "type": [
        -        "string",
        -        "null"
        -      ]
        -    },
        -    "witness": {
        -      "description": "Attestation tier: 'aegis' when backed by a passing 'aegis check --record --tests' row for the current tree, or 'self' for unwitnessed claims.",
        -      "enum": [
        -        "aegis",
        -        "self"
        -      ],
        -      "type": "string"
        -    }
        -  },
        -  "required": [
        -    "credited"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changedaegis_scan3 fields changed
      • changedInput schema / properties / files / description
        Previous value: -"Workspace-relative file paths you are about to edit. When omitted or empty, defaults to modified files in the current git working tree and index."New value: +"Paths you are about to edit; omitted or empty means the files changed in the git work tree and index."
      • changedInput schema / properties / view / description
        Previous value: -"Optional response projection: 'full' (default, complete payload), 'summary' (retains identity/type/status/fitness fields, caps lists at 10 items, and adds <list>_count), or 'ids' (projects each list to rule ID strings). Error responses are never projected."New value: +"'full' (default), 'summary' (key fields, lists capped at 10 plus <list>_count) or 'ids'."
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "error": {
        -      "description": "Error detail when status='FAIL'.",
        -      "type": "string"
        -    },
        -    "guidance": {
        -      "description": "Rendered markdown guidance block ready for prompt injection (omitted when view='summary' or 'ids').",
        -      "type": "string"
        -    },
        -    "invariant_warnings": {
        -      "description": "Mandatory gate and invariant rules triggered by the target files.",
        -      "type": "array"
        -    },
        -    "invariant_warnings_count": {
        -      "description": "Total count of invariant_warnings before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "message": {
        -      "description": "Informational message when status='not_governed'.",
        -      "type": "string"
        -    },
        -    "omitted_mandatory": {
        -      "description": "Mandatory gate or invariant rules that matched but exceeded the two-slot mandatory cap.",
        -      "type": "array"
        -    },
        -    "omitted_mandatory_count": {
        -      "description": "Total count of omitted_mandatory before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "reason": {
        -      "description": "Unbound workspace reason code when status='not_governed'.",
        -      "type": [
        -        "string",
        -        "null"
        -      ]
        -    },
        -    "relevant_rules": {
        -      "description": "Active rules matching the target files, ranked by fitness within the JIT token budget (rule objects in 'full'/'summary' view, or rule ID strings in 'ids' view).",
        -      "type": "array"
        -    },
        -    "relevant_rules_count": {
        -      "description": "Total count of relevant_rules before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "rule_errors": {
        -      "description": "Rule files that failed to parse when status='FAIL'.",
        -      "type": "array"
        -    },
        -    "rules_base": {
        -      "description": "Reviewed git base anchor from which binding gate and invariant rules were loaded.",
        -      "type": [
        -        "object",
        -        "string",
        -        "null"
        -      ]
        -    },
        -    "rules_staged": {
        -      "description": "Count of rules staged in relevant_rules after budget clamping (omitted when view='ids').",
        -      "type": [
        -        "integer",
        -        "array"
        -      ]
        -    },
        -    "rules_staged_count": {
        -      "description": "Total count of rules_staged before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "stale_rules": {
        -      "description": "Rules edited on disk since the last 'aegis sync' derived-file regeneration.",
        -      "type": "array"
        -    },
        -    "stale_rules_count": {
        -      "description": "Total count of stale_rules before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "stats": {
        -      "description": "Scan telemetry summary including matched counts and token budget usage (omitted in 'summary'/'ids' views).",
        -      "type": "object"
        -    },
        -    "status": {
        -      "description": "Optional status indicator ('not_governed' when scanning the user layer outside an Aegis workspace, or 'FAIL' on error).",
        -      "type": "string"
        -    },
        -    "unreviewed_rules": {
        -      "description": "Gate or invariant rules added or modified since rules_base whose local changes do not bind.",
        -      "type": "array"
        -    },
        -    "unreviewed_rules_count": {
        -      "description": "Total count of unreviewed_rules before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    },
        -    "unreviewed_total": {
        -      "description": "Total count of unreviewed gate or invariant rules across the workspace.",
        -      "type": "integer"
        -    },
        -    "user_layer": {
        -      "description": "Read-only user-layer metadata ({path, rules}) when scanning outside a governed Aegis workspace.",
        -      "type": "object"
        -    },
        -    "warnings": {
        -      "description": "Optional non-fatal scan warning messages.",
        -      "items": {
        -        "type": "string"
        -      },
        -      "type": "array"
        -    },
        -    "warnings_count": {
        -      "description": "Total count of warnings before 'summary' view truncation (present when view='summary').",
        -      "type": "integer"
        -    }
        -  },
        -  "required": [
        -    "relevant_rules"
        -  ],
        -  "type": "object"
        -}New value: +null
  2. 5 tool updatesv4.3.4
    • Changedaegis_capture_insight3 fields changed
      • changedInput schema / properties / paths / description
        Previous value: -"Optional workspace-relative file paths this correction applies to."New value: +"Optional workspace-relative file paths this correction applies to (sets psrc='explicit'). When omitted or empty, defaults to currently modified git worktree paths (psrc='dirty')."
      • changedInput schema / properties / quote / description
        Previous value: -"Quote of the user's correction (redacted and capped at 300 chars)."New value: +"Non-empty verbatim quote of the user's correction or preference (1-1024 chars; secrets are automatically redacted and stored text is capped at 300 chars)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Error message when status='FAIL'.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "Content-addressed insight identifier ('ins-<12-hex>').",
        +      "type": "string"
        +    },
        +    "level": {
        +      "description": "Corroboration tier: 'suggestion' initially, or 'W2' when matched to a hook-captured user prompt in the same session.",
        +      "enum": [
        +        "suggestion",
        +        "W2"
        +      ],
        +      "type": "string"
        +    },
        +    "paths": {
        +      "description": "Workspace-relative file paths associated with this insight.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "psrc": {
        +      "description": "Path provenance: 'explicit' when caller supplied paths, or 'dirty' when inferred from git status.",
        +      "enum": [
        +        "explicit",
        +        "dirty"
        +      ],
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "'OK' when the insight row was appended, or 'FAIL' on validation/storage error.",
        +      "enum": [
        +        "OK",
        +        "FAIL"
        +      ],
        +      "type": "string"
        +    },
        +    "text": {
        +      "description": "Secret-redacted and length-capped (max 300 chars) correction quote stored in the ledger.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "status",
        +    "id",
        +    "level",
        +    "text",
        +    "paths",
        +    "psrc"
        +  ],
        +  "type": "object"
        +}
    • Changedaegis_create_rule4 fields changed
      • changedInput schema / properties / description / description
        Previous value: -"The concern, in natural language."New value: +"Non-empty natural-language description of the engineering defect, anti-pattern, or invariant to codify into a rule."
      • changedInput schema / properties / domain / description
        Previous value: -"Optional domain hint."New value: +"Optional domain hint injected into the drafting prompt (e.g., 'security', 'correctness', 'efficiency', 'style', 'governance')."
      • changedInput schema / properties / rule_type / description
        Previous value: -"Optional rule type hint."New value: +"Optional target rule category ('invariant' or 'gate' for blocking checks; 'trap', 'boundary', 'persona', or 'contract' for advisory guidance). Determines the target subdirectory under .aegis/rules/."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Error message when status='FAIL'.",
        +      "type": "string"
        +    },
        +    "instruction": {
        +      "description": "Step-by-step instruction telling the caller where under .aegis/rules/<type_dir>/<id>.md to save the drafted markdown.",
        +      "type": "string"
        +    },
        +    "prompt": {
        +      "description": "Structured rule-generation prompt containing schema requirements and up to three workspace rule examples.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "Present with value 'FAIL' only when input validation fails.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "prompt",
        +    "instruction"
        +  ],
        +  "type": "object"
        +}
    • Changedaegis_list_rules3 fields changed
      • changedInput schema / properties / rule_type / description
        Previous value: -"Optional rule type filter."New value: +"Optional filter restricting both 'rules' and 'stale_rules' to a single rule category ('invariant', 'trap', 'gate', 'boundary', 'persona', or 'contract'). Omit to list all categories."
      • changedInput schema / properties / view / description
        Previous value: -"Optional response projection: full (default), summary or ids."New value: +"Optional response projection: 'full' (default, complete payload), 'summary' (retains identity/type/status/fitness fields, caps lists at 10 items, and adds <list>_count), or 'ids' (projects each list to rule ID strings). Error responses are never projected."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Error message when status='FAIL'.",
        +      "type": "string"
        +    },
        +    "ignored": {
        +      "description": "Non-rule markdown files under .aegis/rules/ with path and reason.",
        +      "type": "array"
        +    },
        +    "ignored_count": {
        +      "description": "Total count of ignored files before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "rules": {
        +      "description": "Workspace rule records with metadata and ledger fitness (or rule ID strings when view='ids').",
        +      "type": "array"
        +    },
        +    "rules_count": {
        +      "description": "Total count of rules before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "stale_rules": {
        +      "description": "Rules edited since the last 'aegis sync' derived-file regeneration.",
        +      "type": "array"
        +    },
        +    "stale_rules_count": {
        +      "description": "Total count of stale_rules before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "status": {
        +      "description": "Present with value 'FAIL' only when the rules directory cannot be safely loaded.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "rules",
        +    "stale_rules",
        +    "ignored"
        +  ],
        +  "type": "object"
        +}
    • Changedaegis_report_outcome9 fields changed
      • changedInput schema / properties / files / description
        Previous value: -"Optional: the files this change edited (workspace-relative). They measure scan-before-edit compliance (aegis status --compliance); they credit no rule."New value: +"Optional workspace-relative file paths edited in this change. Records one 'edit' activity event per idempotency_key for scan-before-edit compliance (aegis status --compliance); does not affect rule credit."
      • changedInput schema / properties / idempotency_key / description
        Previous value: -"Unique key for this report. Retrying with the same key never records twice."New value: +"Caller-supplied unique key (1-256 chars, scoped per host and session). Retrying with the same key and outcome is a no-op; reusing a key with a different outcome fails with status 'FAIL'."
      • addedInput schema / properties / notes / description
        Added value: +"Optional free-text context describing how the rules helped or failed (max 4096 chars)."
      • changedInput schema / properties / outcome / description
        Previous value: -"Verification outcome."New value: +"Verification result for the rules in this change: 'success'/'tp'/'pass' record a true positive ('tp'), 'failure'/'fp'/'fail' record a false positive ('fp'), and 'partial' records a neutral trigger ('trigger')."
      • addedInput schema / properties / rework_count / description
        Added value: +"Optional non-negative integer count of edit-and-retest cycles before verification succeeded (default: 0)."
      • changedInput schema / properties / rules_used / description
        Previous value: -"Names of the rules this outcome is about, as aegis_scan returned them."New value: +"Non-empty list of existing rule IDs from aegis_scan. Validated against the workspace rule inventory; actual fitness credit is computed server-side from session scan exposure and git diff paths."
      • addedInput schema / properties / tests_passed / description
        Added value: +"Optional boolean recording whether the project's test suite passed during verification."
      • changedInput schema / properties / view / description
        Previous value: -"Optional response projection: full (default), summary or ids."New value: +"Optional response projection: 'full' (default, complete payload), 'summary' (retains identity/type/status/fitness fields, caps lists at 10 items, and adds <list>_count), or 'ids' (projects each list to rule ID strings). Error responses are never projected."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "aegis_version": {
        +      "description": "Running Aegis package version string.",
        +      "type": "string"
        +    },
        +    "check": {
        +      "description": "Check record ID that witnessed the report (present when status='recorded').",
        +      "type": "string"
        +    },
        +    "checked_at": {
        +      "description": "UTC ISO-8601 timestamp when the report was processed.",
        +      "type": "string"
        +    },
        +    "credited": {
        +      "description": "Rule IDs credited in the outcome ledger (empty for unwitnessed 'claimed' or 'rate_limited' reports).",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "credited_count": {
        +      "description": "Total count of credited rules before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "error": {
        +      "description": "Error message when status='FAIL'.",
        +      "type": "string"
        +    },
        +    "limit": {
        +      "description": "Per-session report cap (200) returned when status='rate_limited'.",
        +      "type": "integer"
        +    },
        +    "recorded": {
        +      "description": "False when status='rate_limited' or when an unwitnessed claim for the same session and tree was already recorded.",
        +      "type": "boolean"
        +    },
        +    "scope": {
        +      "description": "Workspace scope metadata envelope ({tree}).",
        +      "type": "object"
        +    },
        +    "source": {
        +      "description": "Command or tool name that produced the response ('aegis_report_outcome').",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "Report disposition: 'recorded' (witnessed by a matching check record), 'claimed' (unwitnessed self-report), 'rate_limited' (session cap reached), or 'FAIL'.",
        +      "enum": [
        +        "recorded",
        +        "claimed",
        +        "rate_limited",
        +        "FAIL"
        +      ],
        +      "type": "string"
        +    },
        +    "tree": {
        +      "description": "Git tree hash computed for the workspace at report time.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "witness": {
        +      "description": "Attestation tier: 'aegis' when backed by a passing 'aegis check --record --tests' row for the current tree, or 'self' for unwitnessed claims.",
        +      "enum": [
        +        "aegis",
        +        "self"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "credited"
        +  ],
        +  "type": "object"
        +}
    • Changedaegis_scan3 fields changed
      • changedInput schema / properties / files / description
        Previous value: -"Workspace-relative files you are about to edit. Defaults to the git diff."New value: +"Workspace-relative file paths you are about to edit. When omitted or empty, defaults to modified files in the current git working tree and index."
      • changedInput schema / properties / view / description
        Previous value: -"Optional response projection: full (default), summary or ids."New value: +"Optional response projection: 'full' (default, complete payload), 'summary' (retains identity/type/status/fitness fields, caps lists at 10 items, and adds <list>_count), or 'ids' (projects each list to rule ID strings). Error responses are never projected."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Error detail when status='FAIL'.",
        +      "type": "string"
        +    },
        +    "guidance": {
        +      "description": "Rendered markdown guidance block ready for prompt injection (omitted when view='summary' or 'ids').",
        +      "type": "string"
        +    },
        +    "invariant_warnings": {
        +      "description": "Mandatory gate and invariant rules triggered by the target files.",
        +      "type": "array"
        +    },
        +    "invariant_warnings_count": {
        +      "description": "Total count of invariant_warnings before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "message": {
        +      "description": "Informational message when status='not_governed'.",
        +      "type": "string"
        +    },
        +    "omitted_mandatory": {
        +      "description": "Mandatory gate or invariant rules that matched but exceeded the two-slot mandatory cap.",
        +      "type": "array"
        +    },
        +    "omitted_mandatory_count": {
        +      "description": "Total count of omitted_mandatory before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "reason": {
        +      "description": "Unbound workspace reason code when status='not_governed'.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "relevant_rules": {
        +      "description": "Active rules matching the target files, ranked by fitness within the JIT token budget (rule objects in 'full'/'summary' view, or rule ID strings in 'ids' view).",
        +      "type": "array"
        +    },
        +    "relevant_rules_count": {
        +      "description": "Total count of relevant_rules before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "rule_errors": {
        +      "description": "Rule files that failed to parse when status='FAIL'.",
        +      "type": "array"
        +    },
        +    "rules_base": {
        +      "description": "Reviewed git base anchor from which binding gate and invariant rules were loaded.",
        +      "type": [
        +        "object",
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "rules_staged": {
        +      "description": "Count of rules staged in relevant_rules after budget clamping (omitted when view='ids').",
        +      "type": [
        +        "integer",
        +        "array"
        +      ]
        +    },
        +    "rules_staged_count": {
        +      "description": "Total count of rules_staged before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "stale_rules": {
        +      "description": "Rules edited on disk since the last 'aegis sync' derived-file regeneration.",
        +      "type": "array"
        +    },
        +    "stale_rules_count": {
        +      "description": "Total count of stale_rules before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "stats": {
        +      "description": "Scan telemetry summary including matched counts and token budget usage (omitted in 'summary'/'ids' views).",
        +      "type": "object"
        +    },
        +    "status": {
        +      "description": "Optional status indicator ('not_governed' when scanning the user layer outside an Aegis workspace, or 'FAIL' on error).",
        +      "type": "string"
        +    },
        +    "unreviewed_rules": {
        +      "description": "Gate or invariant rules added or modified since rules_base whose local changes do not bind.",
        +      "type": "array"
        +    },
        +    "unreviewed_rules_count": {
        +      "description": "Total count of unreviewed_rules before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    },
        +    "unreviewed_total": {
        +      "description": "Total count of unreviewed gate or invariant rules across the workspace.",
        +      "type": "integer"
        +    },
        +    "user_layer": {
        +      "description": "Read-only user-layer metadata ({path, rules}) when scanning outside a governed Aegis workspace.",
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Optional non-fatal scan warning messages.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "warnings_count": {
        +      "description": "Total count of warnings before 'summary' view truncation (present when view='summary').",
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "relevant_rules"
        +  ],
        +  "type": "object"
        +}
  3. 5 tool updatesv0.1.0
    • First observedaegis_capture_insight
    • First observedaegis_create_rule
    • First observedaegis_list_rules
    • First observedaegis_report_outcome
    • First observedaegis_scan

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation4/5

Each tool has a distinct role, and the descriptions explicitly resolve the two potential overlaps (aegis_scan vs aegis_list_rules, aegis_report_outcome vs aegis_capture_insight) by stating which one records state. The only residual confusion is that scan and list_rules both return rule sets, so an agent must read the fine print to pick correctly.

Naming Consistency4/5

All names share the aegis_ prefix and follow a verb_noun pattern (create_rule, list_rules, report_outcome, capture_insight), with aegis_scan as the single verb-only deviation. Readable and predictable overall.

Tool Count5/5

Five tools map cleanly onto the guardrails workflow: browse rules, generate a new rule, scan before editing, report verification outcome, and capture user corrections. Nothing appears redundant or padded at this size.

Completeness3/5

The rule lifecycle is incomplete: there is no tool to read, update, retire, or delete an existing rule (aegis_create_rule only builds a prompt and writes nothing), and captured insights cannot be reviewed or dismissed by the agent. These are notable gaps an agent would hit when maintaining rules, though core scan/report flows are covered.

Maintenance

ActivityActive
ResponsivenessUsually handled

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Governance kernel for AI agents — policy enforcement, code safety verification, multi-model hallucination detection (CMVK), trust attestation (IATP), and immutable audit trails. Works with Claude Desktop, Cursor, and any MCP client.
    74
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    AI Constraint Engine that enforces CLAUDE.md, .cursorrules, and AGENTS.md rules as laws. 51 MCP tools for semantic conflict detection, patch review, drift scoring, pre-commit hooks, and Guardian Mode. Catches euphemisms, temporal evasion, and hidden violations that keyword matching misses.
    137 npm
    26
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that enforces repository governance rules for AI coding agents, providing tools to validate plans, diffs, and scan for architectural and safety violations.
    2
    MIT