The discovery engine
When the fleet flags a process no one has documented yet, an anonymous lookup researches it, a verifier checks the sources, and — only if it holds up — it becomes a signed corpus entry everyone benefits from.
The unknown-process problem
Your Mac runs hundreds of background processes, and most of them are undocumented outside Apple. Anomalous ships
with a built-in map of the common ones — it knows, for example, that dasd is Apple's background-activity
scheduler. But no shipped map is ever complete. Sooner or later the sensor flags a process nobody wrote down.
The tempting answer is to let a model guess. Anomalous does not do that. Small on-device models confidently invent identities for processes they have never seen, and a fabricated "safe to kill" is worse than an honest shrug. So Anomalous only speaks about a process when the corpus — its library of verified process identities — actually knows it. The discovery engine is how that library grows to cover the process it just met.
An anonymous lookup
When the fleet meets a process the shipped map does not recognize, the app asks the server about it — anonymously. The request describes only the process: its name, and where known the bundle id, app and OS version, install source, and anomaly type. It never carries anything that identifies you. There is no account link, and none is needed: discovery is a free tier available to everyone.
The request is attested, which cryptographically proves it came from a genuine Anomalous build on real Apple hardware — that keeps the free tier from being flooded with junk. Crucially, the attestation is deliberately never tied to an account. The server can prove the lookup is authentic without being able to prove who sent it.
Under the hood
The Mac app sends POST /v1/discover carrying only process-identity fields. App Attest establishes
build-and-hardware authenticity, but the attested key is stored HMAC'd with the app key, never raw, and no
owner or account is ever attached — the controller is explicitly not owner-scoped
(DiscoveryController::store, lines 22–31, 82–84). The poll handle you get back on a miss is a
random, non-enumerable UUID over public process data. See Privacy for the full
data-handling picture.
Research → verify → publish
On a cache hit the server already knows the process and answers instantly. On a miss, it records the request and kicks off background work in three stages, each one a check on the last.
- Research. An AI agent searches the web, fetches the pages it cites, and drafts a profile: what the process is, who ships it, what a "hot" state implies, and a conservative safety rating. Every specific claim must be backed by a real, cited source URL — inventing a citation is forbidden.
- Verify. A separate, cheaper, independent model re-checks that draft against the actual fetched text of its own citations. It is not the researcher grading itself. A model marking its own homework rationalizes its own hallucinations; a fresh second model is a genuine second opinion.
- Publish or hold back. Only if the verifier says the entry is real, exists on the platform, grounded in its sources, and safely rated does it auto-publish. Anything short of that waits in a human review queue, and the discovery answers "unknown" instead of guessing.
Under the hood
ProcessDiscoveryJob runs the pipeline. Research is DaemonResearchAgent (Claude, with
WebSearch + WebFetch, max 8 steps) producing a DaemonProfile with an existence claim, a
conservative safety_tier, and a required sources[] of {url, title}. The
verifier is DaemonVerifierAgent — a separate, config-driven model (default
claude-haiku-4-5, via anomalous.verifier_model) that can force a more conservative
tier. Fetch and judge are deliberately split into two agents (DaemonSourceReaderAgent reads,
the schema-only verifier judges) because an agent holding both a tool and an output schema forces
tool_choice='any', under which server-side web_fetch never runs. Publish requires
verified === true and confidence >= 0.7
(CONFIDENCE_THRESHOLD); on pass the profile is stamped source='anomalous',
status='approved', published_at=now (ProcessDiscoveryJob.php:39-140).
The pipeline fails closed. With no Anthropic key, research writes a low-confidence stub with nothing to verify, so the answer is "unknown." Verifier exceptions or queue failures also resolve to "unknown," never a spurious publish, and a human-reviewed entry is never silently downgraded. Every failure mode degrades to honesty rather than a false safety claim.
The signed feed
Once an entry is verified, it becomes available to the whole fleet through the corpus feed. Your app does not ask the server about each process it sees. It pulls the entire feed and matches locally, on-device. That distinction is the privacy design: a per-process lookup would tell the server "this user is running X," but a whole-feed pull tells it nothing, and the response is cacheable at the edge.
The feed is signed. The corpus data carries an Ed25519 detached signature, and your app re-computes the canonical bytes and verifies that signature against a pinned public key before any entry is allowed to ground a diagnosis card. A tampered or spoofed feed cannot slip a bad "safe to kill" onto your Mac, because the client — not the server — is the enforcement point.
Under the hood
GET /v1/feed serves the published corpus plus an Ed25519 detached signature over the canonical
(recursively key-sorted, compact, UTF-8) JSON of the data array, with key_id and
signed_at (FeedSigner.php:7-59). It is cached ten minutes and flushed immediately on
any publish or retract via the DaemonProfile saved/deleted hook, so corrections propagate on the
next refresh. key_id lets keys rotate without breaking the fleet. Signing is gated on
ANOMALOUS_FEED_SIGNING_KEY; if that key is absent the feed is served unsigned by design, with a
loud warning, because the client remains the point that enforces trust.
How your card gets grounded
You never touch the discovery engine directly. The payoff shows up quietly: over time, your diagnosis cards can name and explain more processes, with a conservative safety recommendation, instead of showing a shrug. The first person to see a given process pays the research cost once; everyone who meets it afterward gets a free, instant answer. The corpus compounds in value across the fleet.
Cards grounded by the automated verifier are labeled
, distinct from entries a human reviewed. That is one of three trust tiers in the corpus:- anomalous — auto-published after the independent Haiku verifier cleared it, shown as "Sourced by Anomalous."
- reviewed — research or seed data that a human approved.
- community — a GitHub pull request that a human curator approved, with the contributor credited.
The grounding facts are public and correctable. The corpus is an Apache-2.0 data repository — github.com/msitarzewski/anomalous-corpus, one JSON file per process — and PRs are welcome. A wrong "anomalous" entry is fixable by a pull request exactly like any other, and human review always supersedes the automated one. Gaps the engine could not auto-verify are even exported back to the repo as "help wanted" todos, describing precisely why they did not pass, so people who actually know these processes can research and fix them. See the corpus for how contribution and attribution work.