Concept · Reef Engine

What is the Reef Engine?

The Reef Engine is agentmako's durable fact and finding layer — it keeps indexed facts, lint/audit findings, diagnostic runs, freshness labels, and review acknowledgements in local SQLite so an AI coding agent does not have to re-derive the same project knowledge every turn.

TL;DR

Reef is the part of agentmako that remembers things. Indexed facts (file → symbols), diagnostic findings (this file has an eslint error), audit findings (this route is missing a tenant scope), and human acknowledgements (we reviewed this and it's fine) all live in the same local store. Reef tools let the agent ask "what do you already know about this file?" before doing the work over.

Why durable findings matter

Without a persistence layer, every agent session starts from zero. The same lint check runs again. The same auth audit runs again. The same finding is reported, debated, and dismissed — again. The agent has no concept that someone has already looked at this file last week and decided "yes, the missing tenant scope is intentional, the table is read-only by design."

Reef solves this with three primitives that survive across sessions:

  • Facts — derived knowledge ("this function is exported", "this route is GET /api/x", "this table has RLS enabled").
  • Findings — observations that may need attention ("this file has an unused export", "this route is missing an auth guard").
  • Acks — explicit "we reviewed this, it's fine, here's why" markers attached to findings.

Facts vs. findings

The distinction matters because they decay differently.

Facts are descriptive. "This file declares symbol verifySession." A fact is true until the file changes. When the index refreshes, contradicted facts get marked.

Findings are evaluative. "This route handler is missing a tenant scope check." A finding can be: open (still true), resolved (the code was fixed), suppressed (intentionally ignored, with a reason), or stale (the code changed, finding needs re-running).

Tools like file_findings and project_findings read the finding store. project_facts and file_facts read the fact store. reef_inspect shows you both for a given file plus the diagnostic-run history.

Anatomy of a Reef row

Both facts and findings carry enough metadata to answer: who claimed this, when, against what code, and how do I dedup it?

A fact

{
  "factId": "fact_01H8K2…",
  "subjectKind": "file",
  "subjectId": "lib/auth/dal.ts",
  "kind": "exports",
  "value": { "name": "verifySession", "kind": "function" },
  "sourceTool": "project_index_refresh",
  "indexedAt": "2026-04-26T15:14:02Z",
  "fileHash": "a1c2…",
  "freshness": "fresh_indexed"
}

A finding

{
  "findingId": "find_01H8K2…",
  "code": "auth/missing-tenant-scope",
  "severity": "warn",
  "subjectKind": "file",
  "subjectId": "lib/auth/dal.ts",
  "line": 142,
  "column": 9,
  "snippet": "return await db.from('manager_district')…",
  "identity": {
    "matchBasedId": "auth/missing-tenant-scope:lib/auth/dal.ts:142:resolveManagerScope",
    "ruleId": "auth/missing-tenant-scope"
  },
  "sourceTool": "lint_files",
  "createdAt": "2026-04-26T15:14:02Z",
  "lastSeenAt": "2026-04-26T15:14:02Z",
  "status": "open",
  "ack": null
}

The two fields agents lean on most:

  • identity.matchBasedId — a stable fingerprint built from the rule + file + a structural anchor (function name, AST node) rather than line numbers. Surviving across edits is the whole point: when you reformat a file, the finding re-attaches to the same logical site instead of disappearing and re-appearing as a "new" finding.
  • status — one of open, resolved, suppressed, stale. Drives whether the finding shows up in project_findings or project_open_loops.

Freshness, briefly

Every Reef row carries enough metadata to be labeled as live, fresh-indexed, stale, historical, contradicted, or unknown. The agent shouldn't return a stale answer as a confident one — it should know.

Full freshness model: How agentmako tracks freshness.

The ack ledger

Some findings are intentional. A "this file uses any in three places" warning may be the right call for an integration boundary. Acking the finding records: fingerprint of the match, who acked it, why, and when.

Two ack flows exist:

  • finding_ack — single ack, used for one reviewed finding. Requires the fingerprint and a reason.
  • finding_ack_batch — for sweeping reviews. Same payload shape, applied across many findings.

Ack data is never sent anywhere. It's a local ledger. Use finding_acks_report before assuming a clean result means no one suppressed anything — sometimes "all green" is really "all green or already acked."

Don't ack noise. Acks are a real review action. If you're acking findings just to make the dashboard quieter, you're losing the signal Reef was built to keep.

How agents use Reef tools

The most useful tools, in approximate order of how often an agent should reach for them:

  • reef_scout — turn a fuzzy request into ranked facts/findings/rules/diagnostic candidates. First call for many vague tasks.
  • reef_inspect — explain one file or subject: facts, findings, recent diagnostics. First call before editing a sensitive file.
  • file_findings — list active findings for a single file. Quick read before editing.
  • project_findings — active findings across the project. Useful for "what's on fire?" queries.
  • project_open_loops — unresolved findings, stale facts, and failed diagnostic runs in one view.
  • verification_state — whether cached diagnostics still cover current working-tree facts. Tells you if "everything's fine" is current or stale.
  • project_conventions — discovered auth guards, runtime boundaries, route patterns, schema usage conventions — without re-reading the codebase.
  • evidence_confidence — label a piece of evidence as fresh, stale, contradicted, or unknown.

Read-only Reef tools batch well. Use tool_batch when you want freshness, conventions, and open loops in one round-trip.

Lifecycle: how a finding moves

A finding's status is not just a flag — it's the result of a small state machine driven by re-runs of the source tool, file edits, and human review.

             ┌──────────┐
   create →  │   open   │  ─── ack with reason ─→  ┌────────────┐
             └────┬─────┘                          │ suppressed │
                  │                                └────────────┘
       (re-run, still matches)                              │
                  │                                         │
                  ▼                          (file changes,
             ┌──────────┐  ── re-run, no match ─→  ack auto-revoked)
             │  stale   │                                   │
             └────┬─────┘                                   ▼
                  │                                  ┌──────────┐
       (re-run, no match)                            │   open   │
                  │                                  └──────────┘
                  ▼
             ┌──────────┐
             │ resolved │
             └──────────┘

Transitions:

  • open → suppressed: a human (or agent under instructions) calls finding_ack with a reason. The ack is bound to the finding's identity.matchBasedId — not its line number — so it survives reformatting.
  • open → stale: the file changed in a way that may have invalidated the finding, but no diagnostic has re-run yet. The finding still appears in project_open_loops as "needs re-check," not as "still failing."
  • stale → resolved: a re-run produces no matching finding. Reef closes it out automatically.
  • stale → open: a re-run produces the same finding again. The original findingId is reused because matchBasedId matches.
  • suppressed → open: the file changed structurally enough that the structural anchor in matchBasedId no longer matches the ack target. The ack is auto-revoked. This prevents stale acks from hiding real bugs that snuck in during a refactor.

Where Reef lives on disk

Reef is a local SQLite database. There is no hosted Reef service. Two on-disk locations matter:

  • ~/.mako-ai/ — global Mako state (project registry, model-provider keychain references). Not project data.
  • <project-root>/.mako-ai/ — per-project Reef store. Indexed facts, findings, ack ledger, diagnostic run history, scoped instructions all live here.

You can git add .mako-ai/ if you want findings and acks to travel with the repo for the team — or .gitignore it if Reef is one-developer state. Both are valid; the design assumes you can choose.

Privacy note

Reef contents are never sent anywhere. agentmako has no telemetry. The only outbound traffic is the optional model provider you configure for the harness, or the Postgres / Supabase connection you opt in to. See PRIVACY.md.

Reef in practice

Three real workflows that come up often:

Investigating a noisy finding

A diagnostic run produces 30 findings of the same code on the same file after a refactor. Are these new bugs or one existing pattern that the indexer rediscovered?

  1. Call file_findings on the file. Look at createdAt vs lastSeenAt — if all 30 were created in the same run, this is one pattern repeating, not 30 separate bugs.
  2. Open one finding and read its identity.matchBasedId. That tells you whether they're structurally the same site or distinct.
  3. If the pattern is intentional (e.g., a generated SDK file that legitimately uses any), use finding_ack_batch with a clear reason. Future re-runs auto-suppress the same set.

Carrying findings into a new agent session

You ended a long Claude Code session yesterday with several unresolved findings. Today you start fresh.

  1. Have the agent call project_open_loops. It returns yesterday's unresolved findings, stale facts, and any failed diagnostic runs.
  2. For each finding worth investigating, call reef_inspect to get the full evidence trail.
  3. The agent now has the same picture you ended on, without you having to summarize it in a prompt.

Verifying that "all green" is current

Diagnostics passed. But did they pass today?

  1. verification_state reports whether cached diagnostic runs still cover the current working-tree facts.
  2. If it returns stale, the green is from before recent edits — not a current guarantee.
  3. Run diagnostic_refresh to bring it current before relying on the result.

What Reef is not

  • Not a vector store. Reef stores typed rows with stable identities — not embeddings of code chunks. It does deterministic lookups, not similarity search.
  • Not a hosted service. The whole store sits in a local SQLite file under .mako-ai/. No sync, no upload, no SaaS account.
  • Not a replacement for tests. Reef tracks what diagnostics have said and what humans have acked. Your test suite is still authoritative for "does the code work?".
  • Not a static analyzer. Reef is the persistence layer underneath the analyzers (TS, ESLint, Biome, Mako rules). Findings come from those tools; Reef keeps them durable.

Common pitfalls

  • Acking to silence noise. Acks should mean "reviewed and intentional." If you ack to make the dashboard quieter, you're trading durable signal for empty calm. Use finding_acks_report periodically to audit what's been suppressed and why.
  • Trusting stable answers as fresh. cross_search hits Reef, which can be stale. After edits, prefer live_text_search for exact current text, or refresh with project_index_refresh { mode: "if_stale" }.
  • Treating Reef as a TODO list. Findings describe what diagnostics observed, not work you've planned. Use your issue tracker for tasks; use Reef for evidence.
  • Forcing a refresh on every turn. mode: "force" re-parses the whole repo and is slow on large codebases. Reach for it only when indexed answers look wrong, not just old.