verification · git:20260312.5c55e3b · 2026-03-12 · sha256 591983ed8183b516
verification git:20260312.5c55e3bA
Immutable. This exact content never changes and is served at /api/v1/blob/591983ed8183b516.
---
name: verification
description: Verify code against organizational policies, security requirements, and framework best practices. Use when asked to "verify", "review", "audit", "check compliance", or "validate" code.
---
# Agent Verifier
## Purpose
Verify code against business rules, security policies, and framework best practices. All analysis happens locally—code never leaves your machine.
## When to Use
Trigger this skill when the user asks to:
- "verify my code/agent"
- "review code"
- "check compliance"
- "audit my code"
- "check against rules"
- "validate implementation"
## Process
### Step 1: Detect Mode and Load Context
**Check for Kahuna integration** (`.kahuna/` directory exists):
If `.kahuna/` directory exists:
- Context is pre-loaded from `kahuna_prepare_context`
- Use `kahuna_ask` for additional queries
- Read `.kahuna/context-guide.md` for organizational rules and framework patterns
If `.kahuna/` directory does NOT exist (standalone mode):
- Scan for project configuration files
- Apply built-in best practices (see Step 1b)
### Step 1b: Standalone Context Discovery
When running without Kahuna, gather context from the project itself:
**Project configuration files:**
- `package.json`, `pyproject.toml`, `Cargo.toml` - Dependencies and project type
- `tsconfig.json`, `biome.json`, `.eslintrc*` - Linting/formatting rules
- `.env.example` - Expected environment variables
**Documentation:**
- `README.md` - Project overview
- `docs/`, `CONTRIBUTING.md`, `.github/CONTRIBUTING.md` - Guidelines
- `ARCHITECTURE.md`, `DESIGN.md` - Design decisions
**Detect language/framework from:**
- File extensions (`.py`, `.ts`, `.js`, `.go`, `.rs`)
- Dependencies in manifest files
- Directory structure patterns
### Step 2: Discover Files to Analyze
Locate implementation files in the project. Check these common locations:
**Directories:**
- `src/agent/`, `agent/`, `src/`, project root
- `lib/`, `app/`, `packages/`
**Key files to analyze:**
- `graph.py` - Workflow/graph definition (LangGraph)
- `tools.py` - Tool implementations
- `state.py` - State schema definitions
- `prompts.py` - Prompt templates
- `nodes.py` - Node function implementations
- `config.py`, `settings.py` - Configuration
- `*.ts`, `*.js` - TypeScript/JavaScript sources
- `*.go`, `*.rs` - Go/Rust sources
**AI Agent files to prioritize (when agent patterns detected):**
- `graph.py`, `graph.ts` - Agent workflow definitions
- `tools.py`, `tools.ts`, `tools/*.py`, `tools/*.ts` - Tool implementations
- `state.py`, `state.ts` - State schemas
- `prompts.py`, `prompts/*.md`, `system.md` - Prompt templates
- `agent.py`, `agent.ts` - Main agent logic
- `langgraph.json`, `crew.yaml` - Framework configurations
**Exclude from prompt size analysis:**
- `skills/` directory and all subdirectories — these are skill definition files (e.g. `SKILL.md`) loaded on demand by the coding agent, not static system prompts embedded in every LLM call. Flagging them for size would be a false positive.
Use `list_files` or equivalent to discover the actual structure, then read relevant files.
### Step 3: Verify Code Against Rules
#### Check Tiers
Every check in this skill is classified as one of two tiers. Apply them differently:
- **`[PATTERN]`** — Mechanical. The answer is objectively correct or incorrect based on code structure. Apply the rule exactly as written. Do not use judgment to soften or skip. A missing `stop=` parameter on `@retry` is always an ❌ Issue, regardless of context. Report these with high confidence.
- **`[HEURISTIC]`** — Judgment required. The rule describes a quality signal that requires interpretation. Apply it as a best-effort assessment. Mark these findings clearly so the reader knows they reflect analysis, not a deterministic check.
In the report, tag every finding with its tier: `[P]` for pattern, `[H]` for heuristic.
---
Analyze code against all available rules:
**With Kahuna (enhanced mode):**
1. **Organizational rules** - Company policies from `.kahuna/context-guide.md`
2. **IT/Security rules** - Security requirements from knowledge base
3. **Framework best practices** - Patterns from surfaced context
**Standalone (built-in rules):**
1. **`[HEURISTIC]` General code quality**
- Clear naming conventions (descriptive, consistent)
- Appropriate code organization and structure
- Error handling patterns
- No magic numbers/strings without constants
2. **Security basics** — mixed tier (see per-item labels below:)
- `[PATTERN]` No hardcoded secrets — scan for assignments matching `API_KEY`, `SECRET`, `PASSWORD`, `TOKEN`, `PRIVATE_KEY` (case-insensitive) assigned to string literals. Flag any match as ❌ Issue.
- `[HEURISTIC]` Input validation on external data
- `[HEURISTIC]` Proper error messages (no stack traces in production)
- `[HEURISTIC]` Secure defaults
3. **Language-specific (auto-detected):**
*TypeScript/JavaScript:*
- `[PATTERN]` Type safety — flag if `tsconfig.json` does not have `"strict": true`
- `[HEURISTIC]` Async/await error handling
- `[PATTERN]` No `any` types — flag unqualified `: any` annotations as ⚠️ Warning
- `[HEURISTIC]` Dependency security (outdated/vulnerable packages)
*Python:*
- `[PATTERN]` Type hints — flag any `def` function in public scope (no leading `_`) that has parameters without type annotations, as ⚠️ Warning
- `[HEURISTIC]` Docstrings for modules, classes, functions
- `[PATTERN]` Requirements pinning — flag any line in `requirements.txt` / `pyproject.toml` dependencies using `>=`, `>`, or no version specifier (should use `==`), as ⚠️ Warning
*Go:*
- `[PATTERN]` No ignored errors — flag any `_ = ` assignments where the right-hand side is a function call returning `error`, as ❌ Issue
- `[HEURISTIC]` Context propagation
- `[HEURISTIC]` Proper package structure
4. **AI Agent-specific (if detected):**
- `[HEURISTIC]` State schema validation
- `[HEURISTIC]` Tool error handling
- `[HEURISTIC]` Prompt injection considerations
- `[HEURISTIC]` Rate limiting awareness
**Agent Observability Patterns:**
5. **`[PATTERN]` Loop Safety**
Apply mechanically. Do not pass a loop because it "looks like it might terminate."
| Pattern to find | Pass condition | Severity |
|-----------------|----------------|----------|
| `while True:` in Python | A `break` statement exists within the same block scope | ⚠️ Warning if absent |
| `for { }` in Go | A `break` or `return` exists within the block | ⚠️ Warning if absent |
| `while (true)` in TS/JS | A `break` or `return` exists within the block | ⚠️ Warning if absent |
| Function calls itself recursively | A non-recursive return path exists (base case), OR a depth/counter parameter is present | ⚠️ Warning if absent |
6. **`[PATTERN]` Retry Limit Enforcement**
Apply mechanically. Check each decorator or call against the table below. If the required parameter is absent, flag as ❌ Issue regardless of other parameters present.
**Decorator-based (Python):**
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| `@retry` (tenacity) | `stop=stop_after_attempt(n)` or `stop=stop_after_delay(n)` | `stop=` absent |
| `@backoff.on_exception` | `max_tries=n` | `max_tries=` absent |
**HTTP client retry configuration (Python):**
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| `urllib3.Retry(...)` | `total=n` where n > 0 | `total=` absent or `total=0` |
| `HTTPAdapter(max_retries=Retry(...))` | The `Retry` object must have `total=n` | `total=` absent in the `Retry` object passed to `max_retries=` |
| `httpx.HTTPTransport(retries=n)` | `retries=n` where n > 0 | `retries=` absent or `retries=0` |
**AWS SDK (Python/boto3):**
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| `Config(retries={...})` (botocore) | `max_attempts` key with value > 1 | `max_attempts` absent, or `max_attempts: 0` or `max_attempts: 1` (no retries) |
> Note: boto3 clients without any explicit `Config(retries=...)` use the SDK default (3 attempts, standard mode) — do **not** flag the absence of retry config as an issue. Only flag when retry config is present but disables retries.
**JavaScript/TypeScript:**
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| `retry(...)` (async-retry) | `retries: n` in options object | `retries:` absent |
| `pRetry(...)` (p-retry) | `retries: n` in options object | `retries:` absent |
**Custom retry loops (all languages):**
A `while True:` / `while (true)` / `for {}` block that contains a `try/except` (or `try/catch`) with a `continue` or a re-invocation of the same call is a manual retry loop. Apply the same rule as Loop Safety: a bounded counter must be present.
| Pattern to find | Pass condition | Fail condition |
|-----------------|----------------|----------------|
| Loop + `try/except` + `continue` | An integer counter is declared before the loop and incremented inside it, with a conditional check against a max | No counter present → ❌ Issue |
7. **`[PATTERN]` Tool Registry Consistency**
Apply mechanically:
1. Collect all tool names from definition files. A tool name is defined by:
- `@tool` or `@function_tool` decorator on a function → the function name
- A dict/object with a `"name":` or `name:` key at the top level of a tools file
2. Collect all tool name references from prompt files (`.md`, `.txt`, `prompts.py`). A reference is any backtick-quoted identifier or string that names a capability the agent is told it can use.
3. Flag every reference not in the definition list as ❌ Issue (hallucinated tool).
4. Flag every defined tool not mentioned in any prompt as ⚠️ Warning (undocumented tool).
8. **`[PATTERN]` Context Size Awareness**
Apply mechanically using the formula: `token_estimate = len(file_content_chars) / 4`
| Content | ⚠️ Warning threshold | ❌ Issue threshold |
|---------|----------------------|-------------------|
| System prompt file | > 4,000 tokens | > 8,000 tokens |
| Single tool description block | > 500 tokens | > 1,000 tokens |
| All tool descriptions combined | > 2,000 tokens | > 4,000 tokens |
Exclude `skills/` directories from this check (see Step 2).
9. **`[HEURISTIC]` Explicit Tool Listing**
- System prompts should list available tools
- Tool capabilities should be clearly described
*Detection:* Check for tool listing sections (headers like "Available Tools", "You have access to")
For each check, determine:
- ✅ **Pass** - Code complies with the rule
- ⚠️ **Warning** - Potential concern worth reviewing
- ❌ **Issue** - Clear violation that needs fixing
### Step 3b: Agent Pattern Analysis (if AI agent detected)
If the project appears to be an AI agent (LangGraph, CrewAI, AutoGen, LangChain, or custom), perform additional analysis:
**Framework Detection:**
- `langgraph` in imports → LangGraph agent
- `crewai` in imports → CrewAI agent
- `autogen` in imports → AutoGen agent
- `langchain` in imports → LangChain agent
- Custom patterns → Custom agent framework
**Analysis Steps:**
1. **Build tool registry**
Scan all tool definition files: `tools.py`, `tools.ts`, `tools/*.py`, `tools/*.ts`, and any file whose name or content suggests it defines agent tools. Extract tool names using the patterns below. A name found by **any** pattern counts as a registered tool.
**Python — decorator patterns:**
| Pattern | How to extract name |
|---------|---------------------|
| `@tool` (LangChain) on a `def` | Function name immediately below the decorator |
| `@function_tool` (OpenAI Agents SDK) on a `def` | Function name immediately below the decorator |
| `@tool(name="...")` with explicit name arg | Use the `name=` argument value, not the function name |
**Python — dict/list patterns:**
| Pattern | How to extract name |
|---------|---------------------|
| `{"type": "function", "function": {"name": "..."}}` (OpenAI function calling) | Value of the `"name"` key inside `"function"` |
| `{"name": "...", "input_schema": {...}}` (Anthropic tool use) | Value of the top-level `"name"` key |
| `{"name": "...", "description": "...", "parameters": {...}}` (generic schema) | Value of the top-level `"name"` key |
| `ToolNode([func1, func2, ...])` (LangGraph) | Each function name in the list — these must already be registered via decorator or schema above |
| `tools = [func1, func2]` / `TOOLS = [...]` list assigned to a variable | Each identifier in the list — resolve to function names already found by other patterns |
**TypeScript/JavaScript — patterns:**
| Pattern | How to extract name |
|---------|---------------------|
| `{ type: "function", function: { name: "..." } }` (OpenAI) | Value of `name:` inside `function:` |
| `tool({ description: "...", parameters: z.object({...}) })` assigned to a `const name =` (Vercel AI SDK) | The `const` variable name |
| `new DynamicTool({ name: "...", ... })` (LangChain.js) | Value of `name:` |
| `zodFunction({ name: "...", ... })` | Value of `name:` |
After collecting all names, note the total count and source format for the report.
2. **Analyze agent loops**
- Find main execution loops
- Check for termination conditions (break, return, max iterations)
- Verify retry limits on all retry mechanisms
3. **Analyze prompts**
- Measure prompt sizes (estimate tokens)
- Check for tool listings in system prompts
- Verify tool references against registry
- **Exclude `skills/` directories** — files under `skills/` (e.g. `SKILL.md`) are skill definitions loaded on demand, not static system prompts. Do not flag them for context size.
4. **Cross-reference**
- Tools in prompts vs registry (flag mismatches)
- State fields vs usage
- Config vs implementation
5. **LangGraph graph cycle analysis** *(only when LangGraph is detected)*
LangGraph agents define control flow as a directed graph of nodes and edges, not `while` loops. A cycle in the graph is intentional (the agent loops between "agent" and "tools" nodes), but **every cycle must have at least one conditional edge that can route to `END`**. A cycle with no reachable `END` is an infinite loop at the graph level.
**Detection steps:**
a. Find the graph file (`graph.py`, `graph.ts`, or file containing `StateGraph`/`MessageGraph`)
b. Build an edge map by scanning for:
- `workflow.add_edge(source, dest)` — unconditional edge
- `workflow.add_conditional_edges(source, fn, mapping)` — conditional edges; extract all destination values from the mapping dict
c. Identify cycles: find any node that is reachable from itself by following edges
d. For each cycle, check if `END` (or `"__end__"`) is reachable from any node in the cycle via a conditional edge mapping
e. Flag accordingly:
| Condition | Severity |
|-----------|----------|
| Cycle exists, `END` reachable via conditional edge | ✅ Pass |
| Cycle exists, no path to `END` from any node in cycle | ❌ Issue |
| Graph has no `END` node at all | ❌ Issue |
| Node has no outgoing edges and is not `END` | ⚠️ Warning (dead-end node) |
**Example — infinite cycle (❌ Issue):**
```python
workflow.add_edge("agent", "tools")
workflow.add_edge("tools", "agent") # cycle, but no path to END
```
**Example — cycle with exit (✅ Pass):**
```python
workflow.add_conditional_edges("agent", should_continue, {
"continue": "tools",
"end": END # END is reachable → cycle is safe
})
workflow.add_edge("tools", "agent")
```
**Note:** The check inspects the *static structure* of `add_edge` / `add_conditional_edges` calls. It does not evaluate the routing function itself (`should_continue`) — that is runtime behaviour. If the mapping dict contains `END` as a possible destination, the check passes.
**Example findings:**
```markdown
### ⚠️ Warnings
- Potential infinite loop: `agent/loop.py:45`
- **Pattern:** `while True:` without visible break condition
- **Suggestion:** Add explicit max iteration counter: `for i in range(MAX_ITERATIONS):`
- Large system prompt: `prompts/system.md`
- **Size:** ~6,200 tokens (estimated)
- **Threshold:** 4,000 tokens (warning)
- **Risk:** May cause context overflow with long conversations
- **Suggestion:** Consider splitting into base prompt + dynamic sections
### ❌ Issues
- Missing retry limit: `tools/api_client.py:23`
- **Pattern:** `@retry` decorator without `stop` parameter
- **Rule:** All retry mechanisms must have explicit bounds
- **Fix:** Add `@retry(stop=stop_after_attempt(3))` or use `tenacity.stop_after_attempt(3)`
- Hallucinated tool reference: `prompts/system.md:34`
- **Reference:** `execute_sql_query`
- **Available tools:** search_docs, write_file, run_tests
- **Rule:** Tool references must match registered tools
- **Fix:** Either add tool definition or remove reference from prompt
```
### Step 4: Generate Report
Output a structured verification report with agent-specific sections when applicable:
```markdown
# Verification Report
**Project:** [project name or path]
**Date:** [current date]
**Mode:** [Kahuna-enhanced | Standalone]
**Files analyzed:** [count]
**Agent type detected:** [LangGraph | CrewAI | AutoGen | LangChain | Custom | None]
## Summary
✅ X checks passed | ⚠️ Y warnings | ❌ Z issues
### By Category
| Category | Pass | Warn | Issue |
|----------|------|------|-------|
| Code Quality | X | X | X |
| Security | X | X | X |
| Agent Patterns | X | X | X |
## Agent Pattern Analysis
*(Include this section only when Agent type detected ≠ None)*
### Loop Safety
- [x] All retry mechanisms have explicit limits
- [ ] ⚠️ Potential unbounded loop at `[file:line]`
- [ ] ❌ Missing retry limit at `[file:line]`
### Tool Consistency
- [x] Tool registry found: X tools defined
- [ ] ❌ Y hallucinated tool references in prompts
- [ ] ⚠️ Z tools not documented in system prompt
### Context Management
- [x] System prompt within limits (~X tokens)
- [ ] ⚠️ System prompt exceeds recommended size (~X tokens)
- [x] Tool descriptions within limits
## Findings
> `[P]` = pattern-matched (structurally reliable) · `[H]` = heuristic (best-effort judgment)
### ✅ Passing
- `[P]` [Check name]: [Brief confirmation of compliance]
### ⚠️ Warnings
- `[P|H]` [Check name]: [Description of concern]
- **Location:** [file:line if applicable]
- **Suggestion:** [How to address]
### ❌ Issues
- `[P|H]` [Check name]: [Description of violation]
- **Location:** [file:line]
- **Rule:** [Which rule this violates]
- **Fix:** [Specific remediation steps]
## Recommendations
*(Generic recommendations for all projects)*
1. [Priority recommendation based on findings]
2. [Additional improvements]
## Agent-Specific Recommendations
*(Include this section only when Agent type detected ≠ None)*
1. **Loop Safety:** [Add iteration limits / Add retry bounds]
2. **Tool Registry:** [Remove or define hallucinated tools]
3. **Context Management:** [Split large prompts / Add tool documentation]
```
### Step 5: Export Report (Optional)
After presenting the report, ask the user:
> Would you like to save this verification report to a file?
If confirmed:
1. Create the reports directory if it doesn't exist:
```bash
mkdir -p reports/verification
```
2. Generate filename with **actual current timestamp** (not zeros):
```
reports/verification/YYYY-MM-DD_HH-MM-SS.md
```
**Example:** `reports/verification/2026-03-04_16-48-21.md`
Use the current time from the system, not placeholder values.
The format is: `{year}-{month}-{day}_{hour}-{minute}-{second}.md`
3. Save the complete report to that file.
## Notes
- **Privacy first:** All code analysis happens locally. Nothing is sent to external services.
- **Kahuna enhances, not requires:** The skill works standalone with built-in rules. Kahuna adds organization-specific knowledge.
- **Be specific:** Include file names and line numbers when reporting issues.
- **Explain the "why":** Help developers understand why each rule matters.
- **Honor existing configs:** Respect project's existing lint rules, `.editorconfig`, etc.
- **Respect tier discipline:** `[PATTERN]` checks must be applied exactly as specified — do not use judgment to pass something the rule says should fail. `[HEURISTIC]` checks require judgment — apply them thoughtfully and mark findings clearly so the reader understands the confidence level.