Skip to content
Skip to content
All posts
Language
ENDE

Spec Is for Humans, Plan Is for Robots

with Pasha Finkelshteyn

Pasha Finkelshteyn works on the JVM, not on front-ends. In one stream he steered GitHub Copilot through his spec-first workflow to build a Maven plugin that renders a project's dependency graph as one interactive HTML page. His rule: read the spec like a blueprint, and let the agents work through the plan like a schedule nobody needs to read.

Published: October 22, 2026Reading time: 8 min read
Spec Is for Humans, Plan Is for Robots

YouTube

Spec Is for Humans, Plan Is for Robots

Load YouTube video

This video is embedded from YouTube and will only be loaded after your consent. When loading it, personal data may be transmitted to YouTube or Google and cookies may be set.

Open on YouTube

More details are available in the privacy policy.

Project Source

Working Repository

Explore prompts, instructions, and examples used in the live modernization workflow.

Open repository
Session Timeline

Pasha doesn't do front-end. He works on Java performance and the JVM. Yet the dependency graph page we built with AI agents came out, in his words, exactly what we discussed. The reason is the order he works in: design, spec, code.

Pasha Finkelshteyn

Co-Speaker

Pasha Finkelshteyn

Developer Advocate at BellSoft

Pasha has a master's degree in psychology and no technical education. He started programming at 20 in C++ Builder, moved to Java about 19 years ago, and has written Kotlin, Scala and Clojure since. These days, he says, AI writes the code for him.

The blueprint and the work schedule

A building has two documents. The client signs off the blueprint. The crews follow the work schedule. Nobody expects the client to read the schedule.

Pasha's workflow splits AI work the same way. It runs on Superpowers, a set of agent skills. Brainstorming asks you a handful of questions and writes a short spec. Writing plans turns that spec into a long, detailed plan. At 10:31 he summed it up:

It actually creates a very long document which I almost never read. So for me, spec is for humans, plan is for robots.

— Pasha Finkelshteyn, Developer Advocate at BellSoft
100%
For humansFor agentsBrainstormingagent asks,you answerSpecthe blueprint~10 min to readWriting plansspec into tasksPlanthe work schedule8 tasks, rarely readOne subagentper taskred-green TDDFresh reviewerclean context,knows only the taskfixesYou sign off the blueprint. The crews work through the schedule.

Subagent-driven development then hands each plan task to its own agent. The orchestrator picks the model by difficulty: Haiku to retype a file, Sonnet for some integration, Opus for complex judgment. Each task runs red-green TDD, and the plan even names the error the failing test should produce.

After every task, a reviewer subagent checks the work. It knows the task, not the implementer's reasoning. That clean context is the whole point:

I actually don't trust any review done in the same session.

— Pasha Finkelshteyn, Developer Advocate at BellSoft

Where your judgment goes in

The spec is the one document you read, so it's where your decisions have to land. Our prompt was two lines: a Maven plugin that writes one interactive HTML page of the dependency graph. Brainstorming turned that into real decisions over about half an hour.

Some came from Pasha's experience. He wanted scopes switchable, because a runtime dependency that overrides a compile one means you compiled against a different library. He wanted the page fully offline: no CDN, no internet, since a dependency report has no reason to need one. And when we disagreed on a version pinned against dependency management, we didn't force it into "conflict" or "fine". We made a third category, managed override, with its own color.

Hiding parts of the graph went the same way. Pasha wanted to hide a subtree; I wanted to see only what a node depends on. The spec took both, plus every path from the root to a node, in one right-click menu.

Right-click menu on the zipper-core module with the options expand everything below, show only what this depends on, show all paths from root, hide this subtree and reset view; the side panel lists three paths from rootThe right-click menu from the finished plugin's demo: both ways of hiding parts of the graph, plus all paths from the root.
Right-click menu on the zipper-core module with the options expand everything below, show only what this depends on, show all paths from root, hide this subtree and reset view; the side panel lists three paths from root

One decision came from my rambling, which Pasha had come to talk me out of. I asked for a link to Maven Central to check for newer versions. Pasha pointed out that the plugin can just ask Maven Central with a plain HTTP call. Now the page says whether each dependency is the latest, within the same major version and overall. I had asked for a solution, not named my problem. Rambling surfaced it anyway.

The generated dependency graph page: commons-io 2.19.0 is outlined in red because commons-compress wanted 2.16.1; the side panel explains nearest wins, lists both requested versions and paths from the root, and shows an update to 2.22.0 is availableA conflict in the finished page: nearest wins picked commons-io 2.19.0, and the panel shows that 2.22.0 is available.
The generated dependency graph page: commons-io 2.19.0 is outlined in red because commons-compress wanted 2.16.1; the side panel explains nearest wins, lists both requested versions and paths from the root, and shows an update to 2.22.0 is available

Reading the finished spec took about ten minutes. It was worth it. The spec had quietly added optional dependencies, which nobody asked for. That's the kind of thing you catch in a blueprint and miss in an 8-task plan.

We skipped one step for time: Grill with docs, Matt Pocock's skill that walks every decision point and writes ADRs. Pasha said it would have taken another half hour. He once answered grilling questions for three and a half hours before any code was written.

The crews work the schedule

Once we picked subagent-driven development, the plan ran by itself. We spent the time reading what the agents wrote instead of steering them.

The Java side needed only the Maven plugin API, Maven core, the annotations and JUnit. Integration tests used the Maven Invoker plugin with synthetic projects. Pasha last wrote a Maven plugin more than 15 years ago and said he wouldn't have known how to build these tests himself.

The best moment came at 1:27:38. An implementer subagent reported that it had written the code before the tests, with no failing run first. It marked the task "done with concerns". Pasha didn't know why it broke the plan's steps. He liked that it told the orchestrator honestly.

We didn't agree on everything. Pasha defended the hand-written JSON writer the agents produced: it serializes one class, it's tested, and it avoids the risks of a deserializing library. I'd still rather use a maintained library. On var, Pasha uses it everywhere; I like seeing the type. With an agent writing the code, neither of us cared much.

Quality costs time, not tokens

I came in doubting TDD. Doesn't writing a failing test first burn tokens? The numbers at 2:01:43 said less than I thought: about 23.4 million tokens, most of them cached, and 278K output tokens. The cheap models did the routine tasks. Pasha's point: the tests are short and run deterministically. They cost time.

And time was what we ran out of. Pasha predicted the build wouldn't finish in the last 40 minutes, and he was right. We stopped at task 7 of 8: scope switches and the dark and light theme worked, the side panel and search didn't exist yet. A shell also hung for ten minutes doing nothing.

I finished the plugin off-stream. It took about another hour. It's now on Maven Central, and you can try it without touching your POM:

mvn dev.rabauer:dep-graph-maven-plugin:0.2.0:graph

Then open target/dep-graph.html. In a multi-module build, you get one page for the whole reactor:

Dependency graph of a four-module demo build: green module nodes at the top, their direct dependencies below, and a red dashed edge labelled wants 1.26.2 pointing to commons-compress 1.27.1, which is outlined in red as a conflictThe demo build with four modules. The dashed red edge is the version that lost.
Dependency graph of a four-module demo build: green module nodes at the top, their direct dependencies below, and a red dashed edge labelled wants 1.26.2 pointing to commons-compress 1.27.1, which is outlined in red as a conflict

This workflow is not the fastest way to a working page. It is a way to a page that matches what you decided. We chose quality over speed, and I'd make that trade again.

The one skill Pasha wants you to keep

Pasha uses more skills around the core: UI UX Pro Max for design guidelines that fit the kind of app you build, and systematic debugging, which we didn't get to. But one stood out at 20:17:

If you need to remember only one thing from this stream, it is good OSS citizen.

— Pasha Finkelshteyn, Developer Advocate at BellSoft

Good OSS citizen, from Tessl, runs before you open a PR or an issue in someone else's project. It reads the repository and its CONTRIBUTING.md, then reshapes your contribution to fit. Pasha's examples: it splits a PR that's over a project's line limit, or tells you to write the description yourself if the project doesn't accept AI-written text.

Final thought

Pasha's workflow puts you where your judgment counts: in a spec short enough to actually read. Read it like a blueprint, every line. Then let the agents work through the plan, with tests and a reviewer that never saw the implementer's reasoning.

It's slower than prompting and fixing. It also built a front-end that two back-end developers were happy with. Next time, I want to build the same spec with my BMAD process and compare.

Comments

Load comments from GitHub optionally

The comment section is provided via Giscus and GitHub Discussions. It will only be loaded after your explicit consent. When loading it, personal data such as your IP address and technical metadata may be transmitted to GitHub, and cookies or similar technologies may be set.

Please confirm first before loading the comment section.

More details are available in the privacy policy.