<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>aSPARK — Blog</title>
    <subtitle>Notes on deterministic software delivery, policy-as-code and building the aSPARK platform.</subtitle>
    <link href="https://aspark.lottes.dev/en/feed.xml" rel="self"/>
    <link href="https://aspark.lottes.dev/en/blog/"/>
    <updated>2026-09-21T00:00:00.000Z</updated>
    <id>https://aspark.lottes.dev/en/blog/</id>
    <author><name>Andreas Lottes</name><email>andreas@lottes.dev</email></author>
    <entry>
        <title>What a full loop costs: 42 million tokens, $35 — and 96% of it cache</title>
        <link href="https://aspark.lottes.dev/en/blog/was-ein-loop-kostet/"/>
        <updated>2026-09-21T00:00:00.000Z</updated>
        <id>https://aspark.lottes.dev/en/blog/was-ein-loop-kostet/</id>
        <summary>Seven role agents across five phases: one measured run, broken down per role, with the caveats that belong to it.</summary>
        <content type="html">&lt;p&gt;The first question a developer asks on hearing that seven agents carry one feature through five phases is not &amp;quot;how good is the result&amp;quot;. It is: &lt;strong&gt;what does this cost me.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The usual answer in this product category is silence. So here is the number, measured rather than estimated.&lt;/p&gt;
&lt;h2&gt;The case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;todo-filter-bar&lt;/code&gt; — a filter bar for a todo app, built on 19 September 2026 in a single run. From &lt;code&gt;/spark&lt;/code&gt; with a one-sentence feature idea to &lt;code&gt;v0.1.0 released&lt;/code&gt;. All five phases, seven role agents, 29 acceptance criteria, QA in a real browser at desktop width and at 375 px. 47 minutes, five gates, a human decision at every one.&lt;/p&gt;
&lt;p&gt;It is the same session the demo video is cut from.&lt;/p&gt;
&lt;h2&gt;The result&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total tokens&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42,307,448&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;At API list prices (Opus 5)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$35.52&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The same work without prompt caching&lt;/td&gt;
&lt;td&gt;$217.37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Saved by caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$181.85 — 83.7%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The first number is the one that startles. The last one is the one that matters.&lt;/p&gt;
&lt;h2&gt;Why 42 million tokens is the wrong measure&lt;/h2&gt;
&lt;p&gt;Of those 42.31 million tokens, &lt;strong&gt;40.76 million are cache reads — 96.3%&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Fresh input across the entire loop: 960 tokens. Output: 291,732.&lt;/p&gt;
&lt;p&gt;A gated loop re-reads the same context constantly. The spec, while the plan is written. The plan, while the reviewer holds it against the diff. The acceptance criteria, ticked off one by one in QA. That shape of workload is exactly what prompt caching was built for — which is why re-reading costs a tenth of reading.&lt;/p&gt;
&lt;p&gt;Quote the gross figure and you are measuring data volume. Do the arithmetic and you are measuring cost. They are not the same thing.&lt;/p&gt;
&lt;h2&gt;Per role&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th style=&quot;text-align:right&quot;&gt;Output&lt;/th&gt;
&lt;th style=&quot;text-align:right&quot;&gt;Cache read&lt;/th&gt;
&lt;th style=&quot;text-align:right&quot;&gt;Cache write&lt;/th&gt;
&lt;th style=&quot;text-align:right&quot;&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main session (orchestrator + gates)&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;145,113&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;29,697,805&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;411,863&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$21.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QA Tester&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;38,576&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;7,365,329&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;281,134&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$6.41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reviewer&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;25,416&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;1,787,327&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;161,016&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$2.54&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product Owner&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;39,135&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;682,356&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;128,610&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$2.12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Release Manager&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;16,023&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;980,193&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;103,122&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$1.54&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Engineering Manager&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;16,846&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;178,398&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;82,279&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$1.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Designer&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;10,623&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;69,156&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;86,168&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;$0.84&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Two things stand out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The main session carries 59%.&lt;/strong&gt; It is not an agent but the orchestrator: it holds context across all 47 minutes, runs every gate and talks to you. The specialised roles run as subagents with their own, shorter context — they get what they need, not the whole sitting. That is why six agents together cost less than the single thread holding them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The QA Tester is the most expensive individual agent.&lt;/strong&gt; Which fits: it is the only one actually driving a browser — 29 criteria, by mouse and by keyboard, once at desktop width and once inside a 375-pixel frame, plus a run with a hundred todos. Checking costs more than planning. It should.&lt;/p&gt;
&lt;h2&gt;How it was calculated&lt;/h2&gt;
&lt;p&gt;Not from a gut feeling and not from a status line. The numbers come from the &lt;code&gt;usage&lt;/code&gt; fields in this session&#39;s Claude Code transcripts: every assistant message in the main session plus the twelve subagent transcripts. Roles are attributed from the &lt;code&gt;agentType&lt;/code&gt; field in the matching metadata, not assigned by hand.&lt;/p&gt;
&lt;p&gt;Prices as of today, &lt;code&gt;claude-opus-5&lt;/code&gt;, API list:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;per 1M tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;$25.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache read&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache write, 5-minute TTL&lt;/td&gt;
&lt;td&gt;$6.25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache write, 1-hour TTL&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The split between the two TTLs is not assumed but read from &lt;code&gt;usage.cache_creation&lt;/code&gt;: 842,329 tokens at five minutes, 411,863 at one hour.&lt;/p&gt;
&lt;h2&gt;What this number does not say&lt;/h2&gt;
&lt;p&gt;Without this section the rest would be dishonest.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;These are list prices.&lt;/strong&gt; The session ran through Claude Code. On a subscription, nobody paid that $35.52. The figure answers a different question: &lt;em&gt;what does this workload cost when billed at API rates?&lt;/em&gt; That is the comparison figure for someone weighing aSPARK against an alternative — not your invoice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It is one model.&lt;/strong&gt; Opus 5. On a cheaper model the arithmetic changes, and whether the result still passes the same gates is an open question.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It is one data point.&lt;/strong&gt; One feature, one small application, one project. Turning it into an average would be exactly the kind of generalisation this project avoids elsewhere. A second run on a larger feature would be more honest than this one, extrapolated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The 47 minutes are not 47 minutes of model time.&lt;/strong&gt; At five gates a human read and decided. That time is on the clock but not on the bill.&lt;/p&gt;
&lt;h2&gt;Why this is published&lt;/h2&gt;
&lt;p&gt;Because nobody else states this number, and because software that draws its value from being checkable cannot dodge the question of its own cost.&lt;/p&gt;
&lt;p&gt;The calculation is reproducible from the transcripts. Run aSPARK and you can do your own — and if it comes out substantially different, that result is worth more to us than this one.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Your first loop: start with /charter, not with the feature</title>
        <link href="https://aspark.lottes.dev/en/blog/erster-durchlauf-mit-charter/"/>
        <updated>2026-09-20T00:00:00.000Z</updated>
        <id>https://aspark.lottes.dev/en/blog/erster-durchlauf-mit-charter/</id>
        <summary>Install, project profile, first feature: what to do in your first hour with aSPARK — and which decision at each gate is genuinely yours.</summary>
        <content type="html">&lt;p&gt;Since &lt;code&gt;v0.11.0&lt;/code&gt;, aSPARK has one clear starting point. Running &lt;code&gt;/spark&lt;/code&gt; or &lt;code&gt;/next-steps&lt;/code&gt; on a project without a constitution used to leave you between the two — each behaved as if the other had already set things up. Today both point to &lt;code&gt;/charter&lt;/code&gt; first, and &lt;code&gt;/charter&lt;/code&gt; knows what to do whether the repository is empty or has been growing for two years.&lt;/p&gt;
&lt;h2&gt;Install: two commands&lt;/h2&gt;
&lt;p&gt;In a running &lt;code&gt;claude&lt;/code&gt; session:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/plugin marketplace add a-lottes/aSPARK
/plugin install aspark@aspark
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then restart Claude Code — plugins only activate after a restart. A &lt;code&gt;/plugin&lt;/code&gt; afterwards lists &lt;strong&gt;aspark&lt;/strong&gt; as installed and enabled. There is no service, no account and no database: aSPARK is Markdown that works inside your repository.&lt;/p&gt;
&lt;h2&gt;Step 1: /charter, once per project&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;/charter&lt;/code&gt; writes the constitution: the standing rules every phase of every feature inherits. The ceremony behaves differently depending on what it finds.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On an empty repository&lt;/strong&gt; it asks a short set of hard product questions. Who is this for? What do those people do today without it? What is the smallest version that would already help? How will you know it is working? Which stack, which hard constraints? It ends with a proposed constitution and a proposed first slice — both offered for your go, nothing starts unasked.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On a project that already has code&lt;/strong&gt; it reads what is there instead: the README, an existing &lt;code&gt;CLAUDE.md&lt;/code&gt;, existing specs. Out of that comes a bounded project picture — who it is for, the stack, how to run it, conventions, known pain points — which you correct once. After that, the Product Owner and Engineering Manager no longer re-derive the system on every feature.&lt;/p&gt;
&lt;p&gt;Three entries deserve particular attention, because they shape the rest of the loop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project type and characteristics.&lt;/strong&gt; These decide which lenses are active. A public &lt;code&gt;website&lt;/code&gt; gets SEO checks, an &lt;code&gt;api&lt;/code&gt; gets error-envelope and versioning checks, a project that handles payments gets the security lens through every phase. Important: without a constitution, &lt;strong&gt;no&lt;/strong&gt; lens is active. The constitution is the only place a lens is switched on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality bar.&lt;/strong&gt; Whatever sits in §4 no spec has to repeat. If there is no test framework and none should appear, write that down — then nobody builds one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QA method.&lt;/strong&gt; If your project has no surface a browser can drive, declare the substitute method here. Otherwise every feature asks again.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Step 2: the first feature&lt;/h2&gt;
&lt;p&gt;Either phase by phase, or in one go:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/spark A filter bar above the todo list with All, Active, Done …
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;/spark&lt;/code&gt; runs Specify, Plan, Act, Review and Keep, stopping at every gate. You see the artifact and decide. That is not ceremony for its own sake — it is the point: the agents draft, check and recommend; approval is yours.&lt;/p&gt;
&lt;p&gt;What is actually on the table at each gate:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gate&lt;/th&gt;
&lt;th&gt;Your question&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Spec&lt;/td&gt;
&lt;td&gt;Is this the right feature, and are the criteria testable?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plan&lt;/td&gt;
&lt;td&gt;Does the approach hold? Rejecting is still cheap here; after this, code exists.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Findings understood: fix now, or knowingly accept?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QA&lt;/td&gt;
&lt;td&gt;Was every acceptance criterion actually verified?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Release&lt;/td&gt;
&lt;td&gt;Does this ship? Nothing happens without your explicit yes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;After heavy phases, &lt;code&gt;/spark&lt;/code&gt; offers you a &lt;code&gt;/clear&lt;/code&gt; and a fresh start. Take it. The artifacts on disk &lt;strong&gt;are&lt;/strong&gt; the state; a fresh context resumes the loop exactly where it stood, without carrying everything the last phase read.&lt;/p&gt;
&lt;h2&gt;Step 3: extend, optionally&lt;/h2&gt;
&lt;p&gt;Core is complete on its own. Two extensions hook into the loop if you install them:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/plugin install aspark-guard@aspark
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;aspark-guard&lt;/code&gt; moves the gates out of the prompt into a check that runs outside the model, and keeps a hash ledger of every write under &lt;code&gt;.spark/&lt;/code&gt;. &lt;code&gt;aspark-graph&lt;/code&gt; (&lt;code&gt;pip install aspark-graph&lt;/code&gt;) scopes plan, review and QA to the files that are actually involved. Without either, the loop behaves exactly as described — no error, no warning.&lt;/p&gt;
&lt;h2&gt;What you have after the first hour&lt;/h2&gt;
&lt;p&gt;A feature that has passed five gates, and a &lt;code&gt;.spark/&lt;/code&gt; folder you can read, diff and commit: a spec with stories and acceptance criteria, a plan with tasks, a review with findings, a QA report with every criterion checked, and a release note with what was learned.&lt;/p&gt;
&lt;p&gt;Plus a constitution you never have to explain again.&lt;/p&gt;
&lt;p&gt;What such a run looks like in practice is in the &lt;a href=&quot;https://aspark.lottes.dev/en/#showcase&quot;&gt;demo video on the home page&lt;/a&gt;: 47 minutes of a real session, cut to 100 seconds.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Write the idea, not the ticket: keeping the Specify gate short</title>
        <link href="https://aspark.lottes.dev/en/blog/die-idee-formulieren/"/>
        <updated>2026-09-20T00:00:00.000Z</updated>
        <id>https://aspark.lottes.dev/en/blog/die-idee-formulieren/</id>
        <summary>The Product Owner asks about whatever you left open. Anticipate the gaps and you get to a better spec faster — here is the pattern that keeps working.</summary>
        <content type="html">&lt;p&gt;aSPARK&#39;s Product Owner is deliberately not a yes-man. After the first draft it runs a clarify pass that checks the spec against a fixed taxonomy: functional boundaries, data, permissions, error and edge cases, non-functional requirements, integrations, UX states, out of scope. Anything left open comes back as a question.&lt;/p&gt;
&lt;p&gt;That is the point. Those questions are the reason the feature is right afterwards. But how you word your idea decides &lt;strong&gt;which&lt;/strong&gt; of them get asked — the interesting ones, or the obvious ones.&lt;/p&gt;
&lt;h2&gt;The pattern&lt;/h2&gt;
&lt;p&gt;A good idea for &lt;code&gt;/story-time&lt;/code&gt; or &lt;code&gt;/spark&lt;/code&gt; answers in passing what would be asked anyway, and leaves open exactly where you want an opinion. Five things nearly always pay off:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The visible behaviour&lt;/strong&gt;, not the implementation. What does the user see and do? Technical decisions belong in the plan, not in the spec.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The states at the edges.&lt;/strong&gt; What does it say when there is nothing? What happens on the first item, the last one, with a hundred of them?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyboard and focus&lt;/strong&gt;, as soon as there is a UI. This is the question that otherwise comes back, guaranteed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A number or form you can check against.&lt;/strong&gt; &amp;quot;Shows how many are open&amp;quot; is weaker than &amp;quot;shows &lt;code&gt;N items left&lt;/code&gt;, singular &lt;code&gt;1 item left&lt;/code&gt;&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Out of scope, explicitly.&lt;/strong&gt; One sentence about what does &lt;em&gt;not&lt;/em&gt; belong saves a discussion in review and a detour in the plan.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;A real example&lt;/h2&gt;
&lt;p&gt;The feature in our &lt;a href=&quot;https://aspark.lottes.dev/en/#showcase&quot;&gt;demo video&lt;/a&gt; started as exactly one sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Add a filter bar above the todo list with three toggle buttons — All, Active, Done — and a counter that reads &amp;quot;N items left&amp;quot; (singular &amp;quot;1 item left&amp;quot;), counting only active todos. Exactly one filter is selected at a time and is visually marked as selected; All is the default. The list shows only todos matching the selected filter; the counter is independent of the filter. Each filter has its own empty message: &amp;quot;Nothing to do — nice.&amp;quot; for Active, &amp;quot;Nothing done yet.&amp;quot; for Done; the existing &amp;quot;Nothing here yet&amp;quot; message stays for All. Buttons are real &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; elements, operable by keyboard, with the selected one exposed via &lt;code&gt;aria-pressed&lt;/code&gt;. Out of scope: persisting the selected filter across reloads, URL routing, editing todos, animations, and any new dependency or file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Every one of the five points is in there: visible behaviour, three named empty states, keyboard operation, a checkable counter string, and an explicit boundary.&lt;/p&gt;
&lt;p&gt;The Product Owner still pushed back — where it was worth it. One of its questions: when someone ticks a todo with the keyboard under &lt;em&gt;Active&lt;/em&gt;, the row leaves the list immediately. Where does focus go then? I had no answer ready, and the answer became an acceptance criterion. That same detail came back later, when the Reviewer found that the focus ring also stayed after mouse clicks.&lt;/p&gt;
&lt;p&gt;That one sentence became 3 stories and 29 acceptance criteria. The whole loop, idea to release, took 47 minutes.&lt;/p&gt;
&lt;h2&gt;What the pattern does not do&lt;/h2&gt;
&lt;p&gt;It does not shorten the loop; it moves the effort forward. Act, Review and QA take as long as the feature is big. And it does not replace the questions: when the clarify pass finds a gap, that is not a sign of a bad idea — it is the moment a mistake surfaces two hours earlier than it otherwise would.&lt;/p&gt;
&lt;h2&gt;When you have no idea&lt;/h2&gt;
&lt;p&gt;Then do not invent one. &lt;code&gt;/next-steps&lt;/code&gt; surveys the project&#39;s current state — what shipped, what is in flight, what stalled, what the constitution requires — and proposes one concrete next feature. The proposal is advisory; nothing is written or approved. Whatever comes out of it you then hand to &lt;code&gt;/story-time&lt;/code&gt; or &lt;code&gt;/spark&lt;/code&gt; as your idea, ideally worded like the one above.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Why determinism is the more interesting property than speed</title>
        <link href="https://aspark.lottes.dev/en/blog/warum-determinismus/"/>
        <updated>2026-08-07T00:00:00.000Z</updated>
        <id>https://aspark.lottes.dev/en/blog/warum-determinismus/</id>
        <summary>AI assistants make generation cheap. The bottleneck moves to where it was already tight — and determinism is what reopens it.</summary>
        <content type="html">&lt;p&gt;When generating code costs nothing, writing is no longer the bottleneck — everything after it is: understanding, checking, proving. All three presuppose that identical inputs produce identical results.&lt;/p&gt;
&lt;h2&gt;What determinism means here, concretely&lt;/h2&gt;
&lt;p&gt;For aSPARK, determinism does not mean a language model produces the same text twice — it doesn&#39;t, and it doesn&#39;t need to. What is deterministic are the &lt;strong&gt;derived models&lt;/strong&gt;: two builds of an unchanged repository produce a byte-identical &lt;code&gt;graph.json&lt;/code&gt;. The same commitment holds for the sealed snapshots in aSPARK-insights.&lt;/p&gt;
&lt;p&gt;That is a deliberately narrow claim. It is enough to enable three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Comparability.&lt;/strong&gt; A diff between two snapshots shows a real change in the project, not tooling noise.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traceability.&lt;/strong&gt; A query answer can be reproduced instead of merely believed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auditability.&lt;/strong&gt; An audit can rebuild the state instead of relying on a snapshot in time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What it costs&lt;/h2&gt;
&lt;p&gt;Determinism costs expressiveness. A graph allowed to guess could find more connections. aspark-graph does not guess — it tags weak edges as &lt;code&gt;inferred&lt;/code&gt; and fails loudly on template drift instead of quietly bridging it.&lt;/p&gt;
&lt;p&gt;That is the right trade for a tool whose answers feed gate decisions. A graph answer is a map, never a verdict.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;This post is the template for further articles. New posts go in as a Markdown file under &lt;code&gt;src/blog/en/&lt;/code&gt; and appear in the index and feed automatically.&lt;/em&gt;&lt;/p&gt;
</content>
    </entry>
</feed>
