<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0"><channel><title>troupe docs | Blog</title><description/><link>https://troupe.run/</link><language>en</language><fh:complete/><atom:link rel="self" href="https://troupe.run/blog/rss.xml"/><item><title>Six ways to build the same thing</title><link>https://troupe.run/blog/2026-10-10-methodology-bake-off/</link><guid isPermaLink="true">https://troupe.run/blog/2026-10-10-methodology-bake-off/</guid><description>We ran five spec-driven development methods and plain Claude Code through the same seven-step build. All six ended up with working software. They differed most in cost and in how they handled decisions.</description><pubDate>Sat, 10 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Troupe needs a development method to build it until it can run its own builds. To pick one, we put five
spec-driven methods and plain Claude Code through the same seven-step build and scored what came out. It was
a single pass on a single task, with our own harness and rubrics, so treat the numbers as one data point.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-arms&quot;&gt;The arms&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Each arm had its own project, the same model, and the same harness.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Arm&lt;/th&gt;
&lt;th&gt;How it works&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenSpec&lt;/td&gt;
&lt;td&gt;Change proposals with delta specs, archived when done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cc-sdd&lt;/td&gt;
&lt;td&gt;Requirements, design, and tasks, each approved before the next&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kit&lt;/td&gt;
&lt;td&gt;Specify, plan, tasks, implement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kitty&lt;/td&gt;
&lt;td&gt;Spec Kit plus work packages, lanes, and its own issue tracker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Superpowers&lt;/td&gt;
&lt;td&gt;Skills for brainstorming, planning, and subagent-driven development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;td&gt;Claude Code with nothing installed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;the-task&quot;&gt;The task&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The arms built troupe’s configuration tool. It loads a YAML file, lets you read and set values without
losing the file’s formatting or comments, and keeps a history of every change. Later steps added includes, a
watcher that notices hand edits, YAML aliases, and remote includes checked against a schema.&lt;/p&gt;
&lt;p&gt;Each step was a change request on top of the last, so the arms had to live with their earlier decisions. In
step 2 we slipped in a commit from a “teammate” who had worked outside the arm’s process. Step 6 was a bug
report filed as a GitHub issue.&lt;/p&gt;
&lt;p&gt;Every step ran twice. The first run stopped at the arm’s first question or approval request so we could
answer it. A fresh run then built the step with those answers in hand, and that’s the run we scored.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;scoring&quot;&gt;Scoring&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Each arm got a score out of 100. Correctness (20 points) came from hidden tests the arms never saw. Code
quality (15) combined mutation testing, type errors, lint findings, how much code the arm wrote, and how well
the test names describe what they check. I rated every design decision the arms made by what the software
did when we ran it (15). The rest covered coping with change, approval requests, time and cost, fit with
Claude Code, and whether a change could be traced back to its reason. Time, cost, and code size are each
measured against the median arm.&lt;/p&gt;
&lt;p&gt;Three model judges, each told to read from a different perspective, scored the judged parts from anonymised
material, and I decided the cases where they disagreed. The anonymising only went so far, since each
method’s vocabulary tends to give it away.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Arm&lt;/th&gt;
&lt;th&gt;Total /100&lt;/th&gt;
&lt;th&gt;Code quality /15&lt;/th&gt;
&lt;th&gt;Decisions /15&lt;/th&gt;
&lt;th&gt;Interaction /10&lt;/th&gt;
&lt;th&gt;Time and cost /10&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenSpec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;81.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12.2&lt;/td&gt;
&lt;td&gt;10.9&lt;/td&gt;
&lt;td&gt;6.7&lt;/td&gt;
&lt;td&gt;5.8&lt;/td&gt;
&lt;td&gt;$142&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cc-sdd&lt;/td&gt;
&lt;td&gt;77.1&lt;/td&gt;
&lt;td&gt;11.6&lt;/td&gt;
&lt;td&gt;11.2&lt;/td&gt;
&lt;td&gt;7.4&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;$741&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kit&lt;/td&gt;
&lt;td&gt;76.5&lt;/td&gt;
&lt;td&gt;11.3&lt;/td&gt;
&lt;td&gt;10.3&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;4.5&lt;/td&gt;
&lt;td&gt;$273&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kitty&lt;/td&gt;
&lt;td&gt;75.6&lt;/td&gt;
&lt;td&gt;11.7&lt;/td&gt;
&lt;td&gt;10.9&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;$1,543&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Superpowers&lt;/td&gt;
&lt;td&gt;74.5&lt;/td&gt;
&lt;td&gt;8.3&lt;/td&gt;
&lt;td&gt;10.3&lt;/td&gt;
&lt;td&gt;2.7&lt;/td&gt;
&lt;td&gt;9.0&lt;/td&gt;
&lt;td&gt;$27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;td&gt;72.4&lt;/td&gt;
&lt;td&gt;6.4&lt;/td&gt;
&lt;td&gt;8.5&lt;/td&gt;
&lt;td&gt;4.5&lt;/td&gt;
&lt;td&gt;9.3&lt;/td&gt;
&lt;td&gt;$13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;OpenSpec came out ahead, and the other five are too close to rank against each other. We checked how fragile
that was by moving each dimension’s weight five points up and down and pushing every disputed judgement to
its extremes. OpenSpec stayed first in every combination, scoring between 80.4 and 83.0. The next best range
was cc-sdd’s, from 73.6 to 80.6.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;correctness&quot;&gt;Correctness&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Every arm passed 97% to 99% of the hidden tests at every step, the control included. Correctness explains
almost none of the spread in the table.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;time-and-cost&quot;&gt;Time and cost&lt;/h2&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Arm&lt;/th&gt;
&lt;th&gt;Time, all steps&lt;/th&gt;
&lt;th&gt;Cost, scored runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;td&gt;48 min&lt;/td&gt;
&lt;td&gt;$13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Superpowers&lt;/td&gt;
&lt;td&gt;54 min&lt;/td&gt;
&lt;td&gt;$27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenSpec&lt;/td&gt;
&lt;td&gt;2 h 49 min&lt;/td&gt;
&lt;td&gt;$142&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kit&lt;/td&gt;
&lt;td&gt;5 h 22 min&lt;/td&gt;
&lt;td&gt;$273&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kitty&lt;/td&gt;
&lt;td&gt;23 h 44 min&lt;/td&gt;
&lt;td&gt;$1,543&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cc-sdd&lt;/td&gt;
&lt;td&gt;40 h 57 min&lt;/td&gt;
&lt;td&gt;$741&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The cheapest arm cost about a hundredth of the most expensive one. The methods did leave a much better record
of why things changed. With the code, the specs, and the commit messages to go on, the judges gave the control
about 0.6 out of 1 for tracing changes to a stated reason, and gave OpenSpec and cc-sdd full marks.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;questions-and-approvals&quot;&gt;Questions and approvals&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The control and Superpowers went straight to writing code in every first run and asked nothing. The other
four asked between 7 and 23 questions across those runs.&lt;/p&gt;
&lt;p&gt;More often, an arm made a design choice on its own, built it, committed it, and only mentioned it in its
end-of-step summary. One summary was headed “Calls I made where the contract left room.”
Plenty of those calls were reasonable, but by the time I read them, other work was already built on top. I’d
rather have been asked first. In one step an arm did ask me a question, then answered it in its own decision
log before I’d replied. OpenSpec timed its approval requests best, scoring 0.89 of the available points, and
Superpowers scored 0.32.&lt;/p&gt;
&lt;p&gt;Spec Kitty asked the most useful questions, in both runs of each step. It also took the most of my time: 36
minutes at its approval gates, against under four minutes for any other arm. Spec Kit asked nearly all of
its questions in the first runs and then built without stopping. Looking only at its scored runs, you’d think
it never asked anything, so we counted both.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;code-quality&quot;&gt;Code quality&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Four of the methods finished every step with no type errors. Superpowers and the control had 94 and 87 by
step 7, in about 2,000 lines of source each, and the count went up at every step.&lt;/p&gt;
&lt;p&gt;OpenSpec’s lint count rose from 8 to 34 under our ruleset, but 31 of those were unsorted imports, which the
linter fixes in one command. Under OpenSpec’s own lint settings it had none. We now count a finding the linter
can safely fix by itself as a tenth of one, and measure findings per thousand lines.&lt;/p&gt;
&lt;p&gt;Mutation scores ranged from 0.72 to 0.87. The test names ranged from
&lt;code dir=&quot;auto&quot;&gt;test_get_of_a_collection_exits_5_naming_the_path_and_pointing_to_show&lt;/code&gt;, which tells you exactly what broke,
to a single &lt;code dir=&quot;auto&quot;&gt;test_watch&lt;/code&gt; that checked six unrelated behaviours.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;code-size&quot;&gt;Code size&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Every arm built the same features and passed the same hidden tests, with very different amounts of code:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Arm&lt;/th&gt;
&lt;th&gt;Source lines&lt;/th&gt;
&lt;th&gt;Test lines&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;td&gt;1,965&lt;/td&gt;
&lt;td&gt;461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Superpowers&lt;/td&gt;
&lt;td&gt;1,994&lt;/td&gt;
&lt;td&gt;1,187&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenSpec&lt;/td&gt;
&lt;td&gt;3,382&lt;/td&gt;
&lt;td&gt;4,063&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kit&lt;/td&gt;
&lt;td&gt;3,408&lt;/td&gt;
&lt;td&gt;4,867&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec Kitty&lt;/td&gt;
&lt;td&gt;7,403&lt;/td&gt;
&lt;td&gt;16,665&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cc-sdd&lt;/td&gt;
&lt;td&gt;9,773&lt;/td&gt;
&lt;td&gt;34,701&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;cc-sdd wrote five times as much source as the control for the same behaviour, and its tests ran to three and
a half times the size of its source. I’d generally rather have less code. It’s easier to reason about, and it
usually means the arm leaned on libraries instead of writing its own. So source size now counts against the
median arm, with no extra credit below half the median, because code can also be too terse. Test lines aren’t
counted.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-got-in-each-methods-way&quot;&gt;What got in each method’s way&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;OpenSpec does its real work through a separate command-line tool, which the model had to call and parse from
the shell. Its archive step also stops to ask an interactive question, which halts an unattended run. cc-sdd
was the slowest by far, and the model had to remember its phase order and record approvals by hand. Spec Kit
expects a branch per feature, so the model kept hand-writing a pointer file to work on the main branch.
Spec Kitty’s own status checks blocked it, and the model wrote helper scripts to get past them and carried
them through every step. Its tracker also needed an undocumented configuration edit before it would connect.
Superpowers entered its workflow in only one of the seven steps. In the others the model went straight to
code, which is why it scored close to the control. Claude Code itself caused very little of this friction.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-step-6-issue&quot;&gt;The step 6 issue&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Every arm that used GitHub fixed the step 6 bug and left the issue open, with no comment and no link to the
fix. None of those methods has a step that writes back to the tracker. Spec Kitty, which keeps its own
tracker, closed its copy.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;same-design-different-behaviour&quot;&gt;Same design, different behaviour&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Arms that described the same approach to a design question often behaved differently once we ran them. One
kept a comment where another dropped it, and two refused the same bad input with different exit codes. I
ended up rating the behaviour, which meant re-running examples against every arm’s final code.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;problems-every-arm-shared&quot;&gt;Problems every arm shared&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A few problems turned up in all six arms, and the spec we gave them didn’t cover any of them. Some values that
&lt;code dir=&quot;auto&quot;&gt;get&lt;/code&gt; prints don’t mean the same thing when you paste them back into the file, and I’d call that a bug.
History can show an old value until another command happens to run. A command waiting for a lock waits
forever, which isn’t acceptable either. We’ll fix all three in troupe.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-were-doing-next&quot;&gt;What we’re doing next&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We’ll build troupe with OpenSpec for now. It came first under every weighting we tried, did best on
traceability, wrote a moderate amount of code, and cost about a fifth of what cc-sdd did. We’ll answer its
archive question up front so unattended runs don’t stall, run the linter and type checker in the pipeline,
and rely on troupe’s own approval gates for the questions OpenSpec didn’t ask.&lt;/p&gt;
&lt;p&gt;Some of troupe’s design changed too. The configuration file will be generated from recorded events, and a
hand edit is recorded as a change the next time any command runs, &lt;code dir=&quot;auto&quot;&gt;history&lt;/code&gt; included. State will be stored as
text that git can merge, which rules out SQLite. And anything troupe prints should mean the same thing when
you paste it back.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;limits&quot;&gt;Limits&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This was one command-line tool, built once, with one model. One person rated the decisions, and we wrote some
of the rubrics after the first five steps had run. The arms’ projects aren’t public yet. We’ll run a second
pass.&lt;/p&gt;
</content:encoded><category>bake-off</category><category>methods</category></item></channel></rss>