Inspiration

Every developer has a graveyard of half-finished repos. They rarely die because the idea was bad — they die because nobody wrote down what the code was supposed to do. When Kiroween asked for a resurrection, this was the honest reading: you can't revive something without first recovering the intent behind it.

We picked a real corpse. aiorest is an experimental JSON REST framework for aiohttp that its own maintainers declared dead. The last commit is from April 2015. Its README says it plainly:

The development has stopped, the project is abandoned.

What it does

Resurrection runs an abandoned project through Kiro's spec-driven workflow in three stages:

  1. Diagnose — static triage of the repo (dependency declarations, import graph, legacy API surface, async style) produces diagnosis.md: what is broken, what is missing, and what can never come back.
  2. Specify — from that diagnosis, Kiro writes a real spec: requirements.md, design.md, tasks.md.
  3. Revive — it works the task list one verified step at a time. Every task must carry an executable check; a change that fails its check is reverted, not kept.

The output is not just running code — it's the spec the project should have had on day one, so the next person (or the next agent) can pick it up.

How we built it

  • Kiro for diagnosis, spec generation, and the task execution loop
  • Python 3.12 for the scanning and orchestration layer
  • pytest as the verification gate — a task only "passes" when its named test goes green
  • Git as the safety net: every task runs on a branch, unverified changes are reverted

We deliberately chose a target far past the point of a simple dependency bump: aiorest depends on APIs that no longer exist at all.

Challenges we ran into

The root cause was a version constraint, not a bug. setup.py declared install_requires = ['aiohttp>=0.12'] — a lower bound with no ceiling. Eleven years later pip happily installs aiohttp 3.14.5, and the package dies on import:

The tempting fix is to pin aiohttp<1.0 and call it resurrected. That's archaeology, not revival — the project still wouldn't run on any modern Python. So our spec forbids pinning backwards. The migration target is aiohttp 3.x.

One root cause, nine failed test files. pytest tests reports nine collection errors, but they are all the same import chain exploding (__init__.py:37 → server.py:8 → errors.py:14). That was a useful lesson for the diagnosis stage: counting errors lies — you have to trace the chain.

Rewriting isn't renaming. handler.py:17 reads class RESTRequestHandler(aiohttp.server.ServerHttpProtocol). The entire aiohttp.server submodule was removed in 3.x. There is no equivalent class to rename to — the request handling layer has to be rebuilt on aiohttp.web. That single line is where "resurrection" stops being mechanical.

Async style outlived its idiom. The codebase has 20 @asyncio.coroutine decorators and 17 yield from expressions in the source (another 35 and 84 in the tests). asyncio.coroutine was removed in Python 3.11. Every one of those is a hard failure on Python 3.12 — and a task list that names them one by one is 37 tasks long. This is exactly where coarse-grained, unverifiable tasks make things worse: the agent starts rewriting whole modules and the diff becomes unreviewable.

Accomplishments that we're proud of

  • Took a package that could not be imported at all and drove it to a state where its own test suite runs
  • Every single edit in the final report is traceable to a task and to the check that verified it — no "trust me, it works" diffs
  • Produced a spec that explains the migration in terms of intent, not in terms of diffs

What we learned

Spec-driven development isn't really about writing specs upfront. It's about making every step checkable. The moment a task has no verifiable outcome, the agent starts guessing, and guessing is what killed these projects in the first place.

The second thing: a dependency without an upper bound is a scheduled death. Every project we looked at had the same signature — pkg>=x.y and no ceiling — and every one of them died on schedule.

What's next for Resurrection

  • Handle projects with no tests at all: have Kiro write the first smoke test before touching any source file
  • A "resurrection score" that estimates salvageable surface from static analysis alone, so you know how much of a corpse is worth reviving
  • Support multi-language repos where the death is a build-system problem, not an API one

Built With

  • ai-agent
  • aiohttp
  • api-migration
  • code-analysis
  • code-migration
  • developer-tools
  • flask
  • git
  • github
  • jinja
  • kiro
  • legacy-code
  • llm
  • markdown
  • open-source
  • pytest
  • python
  • python-3-12
  • refactoring
  • rest-api
  • spec-driven-development
  • static-analysis
  • tailwindcss
Share this project:

Updates

Submission history