v0.24.0 - let the estate ask, instead of guessing on its behalf
Every list in 0.23.0 was one I wrote by hand after reading process names off a screen. That is the wrong direction — the estate had already observed all of them, and this platform already has the machinery to ask about what it does not recognise. It just was never wired to this surface.
Discovery does it for domains: unknown host, classify, queue, a human decides. The receiver does it for MCP servers, automatically on ingest. CandidateIn has carried a kind field the whole time.
_CANDIDATE_KINDS = ("domain", "mcp_server") before
_CANDIDATE_KINDS = ("domain", "mcp_server", "process") now
Processes become questions
The receiver derives every process name the registry can account for — CLI binaries, desktop app_names, Windows exe_names, allowed_processes — and anything else reaching a model host becomes a candidate carrying its evidence, deduped by name so one script on forty machines is one question rather than forty.
SearchHost.exe, Fireflies.exe and stable should have arrived that way rather than as a commit.
Those sets now live in three services that share no library, so there is a parity test asserting they do not drift — verified failing on a one-word divergence before it passes. Same class of bug as the collector dedupe key: a property that must hold in three places, checked in one.
inference_domains needed unpicking before it could help
build.py refused the field on anything but form: ide, and that rule was correct — the IDE signal was its only reader, and inert configuration reads as working. So the second reader came first: the agentic view now uses it to tell a tool being fetched from one being used. Only then is relaxing the rule honest rather than convenient.
Then the backfill, 2 tools → 15. Safe polarity throughout: a tool that declares nothing is never filtered, so a growing registry can never silently delete findings.
cursor cursor.com -> dropped (a fetch, not a run)
cursor api2.cursor.sh -> kept (a model answered)
claude anthropic.com -> dropped
claude api.anthropic.com-> kept
A scheduled job is now recognised three ways
Tried in order, all registry-driven:
- It names a binary the registry lists. The original signal.
- Its command names an inference host. A job curling
api.anthropic.comon a timer is reaching a model whatever binary it runs.inference_domainsonly, neverdomains— a scheduled installer download is an acquisition, and matching any domain would put every one of them on a page about what runs unattended. - Its definition hands a script a model credential. This closes the blind spot 0.23.0 could only state. A job running
nightly-report.shnames nothing matchable, but a launchdEnvironmentVariablesor systemdEnvironment=settingANTHROPIC_API_KEYsays what it reaches.
Only variables the registry names for a tool. A generic API_KEY would have fired on every scheduled backup in the estate — a worse false positive than the one this whole sequence started with.
Two limits, stated rather than left to be discovered. A Windows scheduled task declares no environment — an action carries a command and inherits the user's — so the credential path cannot exist there, and a wrapper script on Windows stays invisible; the page says so. And EnvironmentFile= is not opened: it points at a file of secrets, and reading the names would mean reading the values.
substrate.office.com suppresses on the domain
For any non-browser, regardless of process. This deletes a maintained list rather than growing one: Microsoft can ship another shell process and it stays quiet without an entry.
The cross-signal join is written down, not built
docs/agentic.md now carries the three reasons it is not sound yet: the join key is a process name (python3 joins against every other python3), it needs inventory rather than findings or it recreates the flood this sequence removed, and an ambiguous join has no honest rendering on a page made of four filled boxes. What the cheap signals miss on a real estate is the specification for it.
Checked
Verified on a real machine and in a container, five job shapes:
runs claude -> reported (binary)
curls api.anthropic.com -> reported (inference host)
runs nightly.sh + ANTHROPIC_API_KEY -> reported (credential)
curls cursor.com/install.sh -> silent
runs backup.sh + AWS_SECRET_ACCESS_KEY -> silent
One job produces one finding: several tools name ANTHROPIC_API_KEY, so the first match wins and the evidence names the variable rather than guessing louder. I caught that as a duplicate during testing, before it shipped.
Suites: registry 23, portal 615, scanner 210, receiver 290. Plus collector parity, build.py --check, both byte-identical invariants, shellcheck, PSScriptAnalyzer, and the containerised Linux collector harness (14/14).
docs/agentic.md updated so the documented signals match the code.