# Hexagon Audit

> Audit Ports & Adapters / hexagonal architecture boundaries in packages/ + adapters/ monorepos. Use for hexagon compliance, port/adapter separation, inward dependency flow, peer-adapter imports, and vendor SDK leaks.

- Skill: `abpai/hexagon-audit` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abpai/hexagon-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abpai/hexagon-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abpai (https://skillmd.com/u/abpai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/abpai/hexagon-audit

---


# Hexagon Audit

Audit Ports & Adapters (Hexagonal Architecture, Cockburn 2005) compliance in a
monorepo that separates interface packages from provider implementations —
typically a top-level `packages/` (ports, shared kernel, inner-core code) and
`adapters/` (provider implementations). This is a read-only audit unless the
user explicitly asks for fixes.

## Invariants

1. **Inward dependency flow.** Files under `packages/` must not import from
   `adapters/`, either by relative path or by a workspace package whose
   `package.json` lives under `adapters/`.
2. **No peer-adapter imports.** An adapter may self-import its own package name,
   but it must not import another package whose `package.json` lives under
   `adapters/`.
3. **Vendor I/O is classified.** Port/interface packages should not import
   vendor SDKs (for example `@modelcontextprotocol/sdk`, `@anthropic-ai/sdk`,
   `@google-cloud/*`, `bun:sqlite`, `postgres`, `pg`, `kubernetes-client`).
   Treat these as findings to classify, not automatic violations.
4. **One adapter, one transport.** Do not bundle two backends in one adapter
   package.

## Process

### 1. Run the deterministic scan

Run the bundled scanner from the repo root. The script path depends on how the
`hexagon-audit` skill is available:

```bash
# installed via `npx skills add` (project-local skills dir)
bun .agents/skills/hexagon-audit/scripts/audit-hexagon.ts

# inside the abpai/skills checkout itself
bun hexagon-audit/skills/hexagon-audit/scripts/audit-hexagon.ts

# loaded as a Claude Code plugin (runtime cache)
bun "${CLAUDE_PLUGIN_ROOT}/skills/hexagon-audit/scripts/audit-hexagon.ts"
```

Pick whichever resolves; if none do, the scanner isn't on disk yet — re-install
or re-add the `hexagon-audit` skill before continuing.

The script discovers workspace package names and dependency edges from
`packages/*/package.json` and `adapters/*/package.json`, then reports:

- `packages/` source or package manifests that import/depend on adapters.
- `adapters/` source or package manifests that import/depend on peer adapters.
- vendor SDK imports and dependency declarations found inside `packages/`.

If the script reports package-to-adapter or adapter-to-peer-adapter imports,
surface them as hard violations. Vendor SDK hits need human classification in
step 3. If the repo does not have `packages/` and `adapters/`
top-level directories, this skill does not apply — say so instead of guessing.

This step is complete when the scanner command, package counts, dependency edge
counts, and any hard-violation candidates are recorded.

### 2. Run focused source checks

Use `rg` to inspect the code around any script findings. These are useful spot
checks, not the source of truth:

```bash
rg -n "from ['\"](\.\./)*adapters/|/adapters/" packages adapters
rg -n "@modelcontextprotocol/sdk|@anthropic-ai/sdk|bun:sqlite|@google-cloud/|^import .*postgres|from ['\"]pg['\"]|kubernetes-client" packages
```

If the script reports an unexpected dependency edge, inspect the corresponding
`package.json` and the source import that uses it.

This step is complete when every deterministic scan hit has either a
`file:line` source citation or an explicit "manifest-only" note.

### 3. Audit by domain group

If subagents are available and the user has explicitly allowed delegation, split
related package/adapter clusters across explorer subagents. Otherwise audit the
groups locally. Group packages with their matching adapters (e.g. a `session`
port with `session-postgres` / `session-sqlite` adapters).

For each group, answer:

- Does any package import an adapter package or path?
- Does any adapter import a peer adapter package or path?
- Are vendor SDKs confined to adapters, or is a `packages/*` module acting as
  runnable inner-hexagon code or shared infrastructure?
- Does each adapter represent one transport/provider?

Adapters may import their port package, shared kernel/domain packages, inner-core
packages, and vendor SDKs. They may not import peer adapters.

This step is complete when every package/adapter group has been classified as
hard violation, soft smell, or clean with cited evidence.

### 4. Classify findings

Sort each finding into one bucket:

- **Hard violation**: `packages/*` imports an adapter, an adapter imports a peer
  adapter, or concrete vendor I/O implementation lives in a package that is
  meant to be a pure port.
- **Soft smell**: a package mixes interface and reference implementation, an
  infra package lives under `packages/` without a clear boundary, or a transport
  name obscures ownership.
- **Clean**: the package is interface-only, shared kernel/domain code, or
  runnable inner-hexagon core with I/O behind abstract ports.

## Report Format

Produce a single markdown report with these sections:

1. **Headline Result**: does the hexagon hold? Include the deterministic scan
   counts and name any hard violations.
2. **Hard Violations**: cite `file:line` for every hard violation.
3. **Soft Smells**: cite `file:line` and explain why it is cleanup rather than
   a blocker.
4. **Clean Groups**: summarize the groups that preserve the boundary.
5. **Recommendations**: split into hard-violation fixes and soft-smell cleanup. Be concrete:
   name the package, adapter directory, or file to move.
6. **Verification**: include the script command and focused `rg` checks so the
   audit can be rerun later.

## Layout Notes

- Storage/provider-shaped code under `packages/` deserves extra scrutiny: it can
  look adapter-shaped even when it is consumed as shared infrastructure.
- Companion repos outside the monorepo are out of scope unless the user includes
  them.

