Two lenses on every orchestrator call
What the plan requires, and what the least that works is. Where they agree, the entry is bulk-approvable. Where they disagree, both sit at equal weight.
A Dataløs plugin · MIT
A plan-execution layer on top of superpowers. The run decides instead of stalling, and logs the call. You triage later. A Change still moves the graph — upstream and down — so a late ruling is not a missed one.
A testimonial from the author
This is the first time I’m actually closing the loop and shipping.
Because I’m using spp.
superpowers · ponytail · frontend-design
The autonomy contract
Autonomous first: an agent that hits an ambiguity does not stall. It takes the most defensible option, returns with the result, and the controller logs it between waves. You catch up with a triage walk. A Change is a direction change — the wave graph already knows who is upstream and who is still waiting, so the ruling travels both ways.
non-consensusD-014 · project
D-011 · D-012 · D-013
What the plan requires, and what the least that works is. Where they agree, the entry is bulk-approvable. Where they disagree, both sit at equal weight.
Non-consensus is never folded away. Project and cross-project blast radius neither. Everything else is one question: accept all N, review individually, or pick some to discuss.
The schedule is a graph, not a queue. Change direction and the waves re-derive: downstream work waits on the new premise, and anything already landed against the old one is flagged, not silently trusted.
Every rule traces to a run that went wrong. Nothing was added because it sounded like good practice.
The eight
The base skill runs one subagent per task and a review after each. That flow is sequential on the page even when the files share nothing. These eight rules are what was missing once the graph was finally drawn.
Two tasks run together when their Creates ∪ Modifies sets are disjoint and every Consumes is already committed. A task’s wave is 1 + max(wave of its dependencies). Derived, so it cannot claim parallelism the graph forbids.
Came from: 13 tasks ran one at a time; six of them shared nothing.One cell per task, showing that task’s own stage. The meter never replaces the explanation. It sits above it, including on the short updates — which is when position is usually dropped.
Came from: status with no sense of position, decaying exactly when updates got long.Anything that constrains an agent belongs inside the quoted brief. Prose outside the quotes is addressed to the controller. An unstated prohibition leaves the agent’s own skills in force.
Came from: agents deciding without the context that would have changed the decision.Mandatory, and not a formality. Agents no longer stop to ask, so nothing halts a wave when the plan itself is wrong. Finding several defects before any code is written is normal. That is the point of the pass.
Came from: three self-contradictions in one plan, found before task 1.The review hunts code that produces a plausible wrong answer instead of failing. Tests pass. The run reports success. The number is used to make a decision.
Came from: nearly every serious finding in the original run.When a task runs against real data, the figure is a domain result, not test output. Investigate any number that surprises you before it flows downstream. Plausible is not correct.
Came from: a 24% gap visible only in one task’s output figure.At about 50%, stop taking on new work and hand off. Not at 70% because the current task feels nearly done. A returned agent whose findings exist only in the conversation is unprocessed.
Came from: a window that ran out mid-task with subagent output unprocessed.Wave plans and figures describe how this run proceeded. Judgement calls outlive it and go to the decision log. The controller writes that log, between waves. If you are unsure whether something is log-worthy, it is.
Came from: controllers re-dispatching completed work after compaction.The review lens
Ordinary review asks whether code is correct. This catalogue asks how it would be wrong without telling you. None of these raise. All of them produce a confident number.
A parse fails and yields 0. Zero is a legitimate value, so it becomes a result.
A pattern handles the common shape and is silent on the variant. Observed: 24% unparsed.
A loop continues past malformed input with no counter. The output looks complete.
“Items processed” after dedup, replacement, or drop. The number reassures while the data shrinks.
Trades a wrong-value bug for a missing-record bug, which is strictly worse.
Each step is defensible. The sum sits outside the brief.
Never observed failing, so they lock in nothing.
The column would have been uniformly zero. Two opposite conditions, identical.
A test asserting the opposite of the function it tests. Every implementer executes it faithfully.
exit 128 → wc -l prints 0 → “prints nothing” passes. Four instances, one phase.
A check that reports success without having executed. Indistinguishable from a real pass.
An assertion with nothing behind it. “Six of them” — there were ten.
The better predicate wired in front of the old check. The guarantee left with the old code.
A prohibition one line outside the closing quotation mark. Silence resolves to the wrong default.
An assertion never observed failing is not an assertion. The decisive test is removing what it detects.
One line. Global for your user, or --project for this repo only. --with-deps also installs superpowers, ponytail, and frontend-design. Detects Claude, Grok, Cursor, Codex, Gemini, and the rest of the GSD tool set.
# this user (default) curl -fsSL https://spp.datalos.dk/install.sh | sh # this user, with companions curl -fsSL https://spp.datalos.dk/install.sh | sh -s -- --with-deps # this project only curl -fsSL https://spp.datalos.dk/install.sh | sh -s -- --project
Then invoke /spp before dispatching task 1. Update with /spp-update. The files come from github.com/mikl0s/spp.
A note
This was written for Claude, and it has been run on Codex and the rest of the set. Grok 4.6 on high is what packaged it — this page, the public repo, a private setup walked far enough that someone else can install it. That is how the fit showed up: Grok takes a message as a task, not a chat. One task is a full wave, so you stop making small asks and make a more complex one. The graph does the splitting.