Oleg Fedorets is a Finnish astronomer who studies minimoons — small solar system objects temporarily captured by Earth's gravity. They are hard to find. They are hard to classify. The Vera C. Rubin Observatory, when it begins full science operations, will generate 20 terabytes of alert data every night for ten years. Somewhere in that data, minimoon candidates will appear for a few nights and then vanish.
Oleg needed a pipeline. He did not have months to build one. He had a research problem and a collaborator — me — who builds software for a living.
We built it in two days.
What We Built
The repository is fedorets/lsst-extendedness on GitHub.
This is not a demo. It is not a proof of concept with a "TODO: add tests" comment at the top of every file. It is production-ready scientific software with a proper test suite, a CI/CD pipeline, Dependabot dependency updates, and auto-merge for passing patch updates.
The pipeline does the following:
- Connects to the Fink broker REST API, which aggregates and filters the LSST alert stream
- Applies an extendedness filter:
extendedness = 1 - classtar, threshold> 0.7— objects that are not point sources (stars are point sources; moving solar system objects are not) - Classifies candidates against known solar system object catalogs
- Stores results in SQLite with Pydantic-validated models
- Exposes a Click CLI for manual runs and debugging
There are six pluggable alert sources: ANTARES, Kafka, Fink, SpaceRocks (JPL Horizons for known asteroid orbits), File, and Mock. The architecture is designed to survive the LSST alert format changing, which it will.
The Scale Problem This Is Solving
LSST will process roughly 10 million alerts per night. Over its ten-year mission, it will accumulate 60 petabytes of data. The Fink broker sits between that firehose and researchers: it ingests the raw ZTF and LSST alert streams, applies machine learning classifiers, and makes filtered subsets available via REST API.
A minimoon candidate looks, briefly, like a fast-moving object with non-stellar morphology. It might appear in three consecutive nights of observations, arc across the sky at an unusual rate, and then either escape Earth's gravity or impact. The classification window is short. If you are not running a pipeline that checks the Fink alert stream continuously, you miss it.
Oleg knew what the filter should be. The problem was wrapping that domain knowledge in infrastructure that would actually run reliably.
How AI-Augmented Development Changed the Economics
The question worth asking is not "did AI write the code?" The answer is complicated and not especially interesting. The question worth asking is: what would this have cost without AI-augmented development?
A pipeline with 23,000 lines of code, 96% test coverage, and a CI/CD configuration does not get built in two days by a single developer working conventionally. It gets built in two to four weeks by a small team, or in six to eight weeks by a solo researcher who is also writing papers and teaching. The research would still happen; the software would lag behind it, probably permanently.
AI-augmented development collapses the gap between a researcher's domain knowledge and the implementation of a production system.
What AI does not replace: knowing that classtar is the right morphology metric, knowing that the Fink API has specific quirks around pagination, knowing that minimoon candidates have particular proper motion signatures that distinguish them from artifacts. That knowledge is Oleg's. The AI amplified his ability to encode that knowledge into working software.
The researcher does not need to become a senior engineer. The engineer does not need to become an astronomer. Both need to be present; one of them now has a significant force multiplier.
The MCP Server Layer
One of the less obvious architectural choices was wrapping the pipeline in an MCP server — Model Context Protocol, the standard that allows AI assistants to call external tools during a session.
The pipeline can answer questions: which alerts triggered the extendedness filter last night? What is the proper motion distribution of current candidates? How many objects passed through the full classification pipeline in the last seven days? These are questions a researcher might ask repeatedly, in slightly different forms, while writing a paper or preparing an observation proposal.
Without the MCP layer, those questions require writing a query, running it, interpreting the output, and iterating. With the MCP layer, an AI assistant can query the pipeline directly as a tool call. The astronomer describes what they want to know; the tool retrieves it.
This is not replacing scientific judgment. It is removing the friction between scientific judgment and the data that informs it.
The Knowledge Graph Integration
Across the 48 hours of development, hundreds of decisions were made: why this alert schema and not that one, why SQLite and not PostgreSQL, why this particular threshold for the extendedness filter, why five alert sources when we only need one today. In a conventional project, these decisions live in Slack threads, commit messages, and the memory of the people who were in the room.
We stored them in a knowledge graph — a PostgreSQL database with pgvector that runs as a persistent service. Every architectural decision became a queryable entity. Every relationship between components was recorded as a relation.
At the start of each work session, the relevant context was loaded from the knowledge graph rather than reconstructed from memory or re-read from files. This compresses the startup cost of returning to a project after a break. It also means the decisions survive the engagement: when Oleg picks this up in three months to extend it for a new data source, the reasoning is retrievable, not reconstructed.
A knowledge graph that remembers why a decision was made is worth more than comments that describe what the code does. The former is queryable. The latter is read once and forgotten.
What "Production Ready" Actually Means for Research Software
Research software has a reputation for fragility. It runs on the author's laptop, with hardcoded paths, no error handling, and tests that consist of "I ran it and it worked." This is not a character flaw in researchers; it is a resource allocation problem. Writing production-quality software takes time that most researchers do not have.
Here is what production ready means for this pipeline:
- Tests that run in CI — every commit triggers the test suite. A failing push does not merge. If Oleg extends the filter logic and breaks an edge case, he finds out before the code reaches the pipeline that runs against live LSST data
- Dependabot with auto-merge — security patches to dependencies merge automatically when the test suite passes. The pipeline does not accumulate CVEs because no one had time to run
pip install --upgrade - Pluggable alert sources — the pipeline does not break if Fink changes their API or if Oleg wants to test against a local file of historical alerts. The source is an interface, not a hardcoded HTTP call
- Pydantic models — every alert that enters the pipeline is validated against a schema. Malformed data raises an exception with a clear error message rather than producing a silent wrong result
- A Click CLI with --help that works — this sounds trivial. For research software, it is not
- Fixing the ecosystem, not just the project — the pipeline depended on the standalone
bsonpackage, abandoned since 2019 and broken on Python 3.12+ due to removedpkgutil.find_loader()and asixdependency. Rather than work around it, I forked it, stripped the Python 2 code, modernized tohatchling, published it to PyPI as bson-modern, and submitted a PR back to the upstream science project. Production ready means the dependencies are production ready too
The 96% test coverage is not a vanity metric. It means that when the Rubin Observatory alert format evolves — and it will evolve — the tests will tell us exactly which adapters broke and which continued to work.
The Honest Assessment
Two days is fast. Fast enough that it should prompt some skepticism about quality.
The skeptical reading: we built 23,000 lines quickly because AI-assisted development fills in boilerplate without understanding the domain. The tests pass because they were written to match the implementation, not to specify the behavior independently.
This criticism has teeth, and I will not dismiss it. The counter-argument is the test architecture: the 604 test functions include property-based tests, edge case coverage for malformed inputs, and integration tests that run against Mock alert sources with known outputs. Tests written to rubber-stamp an implementation do not catch regressions; these tests do.
The more honest limitation: two days is enough to build the infrastructure. It is not enough to validate the science. Whether the extendedness threshold of 0.7 is the right cut, whether the proper motion filters correctly distinguish minimoons from artifacts, whether the Fink classifier outputs are being interpreted correctly — these are questions that require Oleg's domain expertise and, ultimately, comparison against real LSST data when it arrives. The pipeline is ready for that validation. The science is not finished because it was never the claim that it would be.
The Economics of Research Software
European research institutions spend significant money on software development for scientific pipelines. Some of it goes to dedicated RSE teams. Most of it goes to graduate students who learn Python well enough to make things work, ship a paper, and then leave, taking the working knowledge of the system with them.
The structural problem is that the gap between "researcher with domain knowledge" and "production-quality software" has historically required a team and months. AI-augmented development narrows that gap significantly. A Finnish astronomer and a fractional CTO who builds AI infrastructure can produce, in two days, software that would have taken a small team weeks.
This does not replace research software engineers. It does change the economics of what is feasible for a single research group without dedicated software support. Projects that would have waited for the next graduate student or the next grant cycle can now reach production-quality implementation faster.
The Rubin Observatory will change what is findable in the solar system. The software that finds those things needs to be ready. It is now.