@loneexile/omp-superpowers 7.0.1-omp.1 → 7.0.1-omp.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.pi/extensions/superpowers.ts +114 -2
- package/CHANGELOG.md +20 -1
- package/README.md +124 -50
- package/package.json +1 -1
- package/skills/brainstorming/SKILL.md +12 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
@@ -10,8 +10,15 @@ const extensionDir = dirname(fileURLToPath(import.meta.url));
|
|
|
10
10
|
const packageRoot = resolve(extensionDir, "../..");
|
|
11
11
|
const skillsDir = resolve(packageRoot, "skills");
|
|
12
12
|
const bootstrapSkillPath = resolve(skillsDir, "using-superpowers", "SKILL.md");
|
|
13
|
+
const SKILL_URL = /skill:\/\/([a-z0-9][a-z0-9-]*)/g;
|
|
14
|
+
// An SDD workspace directory, as sdd-workspace prints it or as part of a path
|
|
15
|
+
// into it; the ledger is its progress.md. Dot-names (`.gitignore`) and the old
|
|
16
|
+
// flat `.superpowers/sdd/progress.md`, which SDD's own text mentions, are not plans.
|
|
17
|
+
const SDD_WORKSPACE = /[^\s"'`()<>[\]\\]*\.superpowers\/sdd\/[A-Za-z0-9_-]+(?![\w.-])/g;
|
|
18
|
+
const MAX_SKILLS_NAMED = 4;
|
|
13
19
|
|
|
14
20
|
let cachedBootstrap: string | null | undefined;
|
|
21
|
+
let cachedSkillNames: Set<string> | undefined;
|
|
15
22
|
|
|
16
23
|
export default function superpowersPiExtension(pi: ExtensionAPI) {
|
|
17
24
|
let injectBootstrap = true;
|
|
@@ -28,6 +35,13 @@ export default function superpowersPiExtension(pi: ExtensionAPI) {
|
|
|
28
35
|
injectBootstrap = true;
|
|
29
36
|
});
|
|
30
37
|
|
|
38
|
+
// The compaction summary does not carry skill text. Name the superpowers
|
|
39
|
+
// skills read before it and the plan's ledger, so the agent reads them again.
|
|
40
|
+
pi.on("session.compacting", async (event) => {
|
|
41
|
+
const context = compactionContext(event?.messages ?? []);
|
|
42
|
+
return context.length > 0 ? { context } : undefined;
|
|
43
|
+
});
|
|
44
|
+
|
|
31
45
|
pi.on("session_switch", async () => {
|
|
32
46
|
injectBootstrap = true;
|
|
33
47
|
});
|
|
@@ -45,9 +59,17 @@ export default function superpowersPiExtension(pi: ExtensionAPI) {
|
|
|
45
59
|
const bootstrap = getBootstrapContent();
|
|
46
60
|
if (!bootstrap) return;
|
|
47
61
|
|
|
62
|
+
const content: Array<{ type: "text"; text: string }> = [{ type: "text", text: bootstrap }];
|
|
63
|
+
// After a compaction, name the superpowers skills and ledger used before it.
|
|
64
|
+
// Read from the session branch, so it holds whatever the compaction method
|
|
65
|
+
// and also after a restart or `omp -c`.
|
|
66
|
+
if (event.messages.some((message) => field(message, "role") === "compactionSummary")) {
|
|
67
|
+
const note = compactionContext(messagesBeforeLatestCompaction(ctx));
|
|
68
|
+
if (note.length > 0) content.push({ type: "text", text: note.join("\n") });
|
|
69
|
+
}
|
|
48
70
|
const bootstrapMessage = {
|
|
49
71
|
role: "user" as const,
|
|
50
|
-
content
|
|
72
|
+
content,
|
|
51
73
|
timestamp: Date.now(),
|
|
52
74
|
};
|
|
53
75
|
|
|
@@ -111,6 +133,96 @@ From omp 18.4.12 every subagent is told to leave builds, tests and smoke runs to
|
|
|
111
133
|
If your tools include \`vibe_spawn\` but not \`task\`, omp's vibe mode is on and you are its director: you have none of the \`task\`, \`bash\`, \`edit\` or \`write\` tools named above. Read the "Vibe mode" section of \`skill://using-superpowers/references/pi-tools.md\` before acting on them.`;
|
|
112
134
|
}
|
|
113
135
|
|
|
136
|
+
// Reads one property of an unknown value; undefined unless it is an object holding it.
|
|
137
|
+
function field(value: unknown, key: string): unknown {
|
|
138
|
+
return value !== null && typeof value === "object" && key in value ? Reflect.get(value, key) : undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function messagesBeforeLatestCompaction(ctx: unknown): unknown[] {
|
|
142
|
+
const sessionManager = field(ctx, "sessionManager");
|
|
143
|
+
const getBranch = field(sessionManager, "getBranch");
|
|
144
|
+
if (typeof getBranch !== "function") return [];
|
|
145
|
+
let entries: unknown;
|
|
146
|
+
try {
|
|
147
|
+
entries = getBranch.call(sessionManager);
|
|
148
|
+
} catch {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
if (!Array.isArray(entries)) return [];
|
|
152
|
+
let end = -1;
|
|
153
|
+
entries.forEach((entry, index) => {
|
|
154
|
+
if (field(entry, "type") === "compaction") end = index;
|
|
155
|
+
});
|
|
156
|
+
return entries
|
|
157
|
+
.slice(0, Math.max(end, 0))
|
|
158
|
+
.filter((entry) => field(entry, "type") === "message")
|
|
159
|
+
.map((entry) => field(entry, "message"));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function compactionContext(messages: unknown[]): string[] {
|
|
163
|
+
const ours = superpowersSkillNames();
|
|
164
|
+
const skills: string[] = [];
|
|
165
|
+
let ledger: string | undefined;
|
|
166
|
+
|
|
167
|
+
for (const message of messages) {
|
|
168
|
+
for (const part of contentParts(message)) {
|
|
169
|
+
if (part.type === "toolCall") {
|
|
170
|
+
const args = JSON.stringify(part.arguments ?? {});
|
|
171
|
+
for (const match of args.matchAll(SKILL_URL)) {
|
|
172
|
+
const name = match[1];
|
|
173
|
+
if (!ours.has(name)) continue;
|
|
174
|
+
const seen = skills.indexOf(name);
|
|
175
|
+
if (seen !== -1) skills.splice(seen, 1);
|
|
176
|
+
skills.push(name);
|
|
177
|
+
}
|
|
178
|
+
ledger = lastLedgerPath(args) ?? ledger;
|
|
179
|
+
} else if (part.type === "text" && typeof part.text === "string") {
|
|
180
|
+
ledger = lastLedgerPath(part.text) ?? ledger;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (skills.length === 0) return [];
|
|
186
|
+
const named = skills.slice(-MAX_SKILLS_NAMED).map((name) => `skill://${name}`).join(", ");
|
|
187
|
+
const lines = [
|
|
188
|
+
`Superpowers skills in use before this compaction (most recent last): ${named}. This summary does not carry their text: before your next step, read again the ones you are still following.`,
|
|
189
|
+
];
|
|
190
|
+
if (ledger) {
|
|
191
|
+
lines.push(`Superpowers ledger: ${ledger}. Read it before you continue; it records what is done and what is next.`);
|
|
192
|
+
}
|
|
193
|
+
return lines;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function superpowersSkillNames(): Set<string> {
|
|
197
|
+
if (cachedSkillNames) return cachedSkillNames;
|
|
198
|
+
try {
|
|
199
|
+
cachedSkillNames = new Set(
|
|
200
|
+
readdirSync(skillsDir, { withFileTypes: true })
|
|
201
|
+
.filter((entry) => entry.isDirectory() && existsSync(resolve(skillsDir, entry.name, "SKILL.md")))
|
|
202
|
+
.map((entry) => entry.name),
|
|
203
|
+
);
|
|
204
|
+
} catch {
|
|
205
|
+
cachedSkillNames = new Set();
|
|
206
|
+
}
|
|
207
|
+
// The bootstrap re-injects using-superpowers after every compaction already.
|
|
208
|
+
cachedSkillNames.delete("using-superpowers");
|
|
209
|
+
return cachedSkillNames;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function contentParts(message: unknown): Array<{ type?: unknown; text?: unknown; arguments?: unknown }> {
|
|
213
|
+
const content = field(message, "content");
|
|
214
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
215
|
+
if (!Array.isArray(content)) return [];
|
|
216
|
+
return content
|
|
217
|
+
.filter((part) => part !== null && typeof part === "object")
|
|
218
|
+
.map((part) => ({ type: field(part, "type"), text: field(part, "text"), arguments: field(part, "arguments") }));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function lastLedgerPath(text: string): string | undefined {
|
|
222
|
+
const matches = text.match(SDD_WORKSPACE);
|
|
223
|
+
return matches ? `${matches[matches.length - 1]}/progress.md` : undefined;
|
|
224
|
+
}
|
|
225
|
+
|
|
114
226
|
function messageContainsBootstrap(message: unknown): boolean {
|
|
115
227
|
const content = (message as { content?: unknown }).content;
|
|
116
228
|
if (typeof content === "string") return content.includes(BOOTSTRAP_MARKER);
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,23 @@ A version is `<upstream version>-omp.<n>`: the upstream release this fork is syn
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [7.0.1-omp.3] - 2026-10-24
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **After a compaction, the bootstrap names the superpowers skills read before it and the plan's ledger.** The extension reads them from the session branch, so the note holds whatever the compaction method and after `omp -c`; it also hands the same lines to the compaction summarizer through `session.compacting`. Checked live on omp 18.12.6 from the installed plugin path: the note was computed at compaction and sent with the bootstrap on each request of the next turn. It has not yet been shown to change behavior. In a short brainstorm-then-build run compacted mid-conversation, agents re-read the brainstorming skill and kept the small-change path in 5 of 5 runs with and without this change. In a six-task subagent-driven-development run compacted with `/compact` after its first wave (`remote` summary compaction, memory and the advisor off), the controller re-read the SDD skill and the ledger before anything else, redid no finished task and finished the plan in 2 of 2 runs with and without it; the note named the SDD skill and the ledger, but that summary already did too. It is aimed at a compaction whose summary drops a skill's rules.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **The README is easier to read.** It opens with what the fork is and a short get-started section, adds a diagram of how a request flows by its size, and folds the reference material (other install routes, how a seat's model is chosen, the file-by-file list of changes, maintenance) into expandable sections. No fact was dropped; the `task.isolation` notes are now marked as re-checked live on omp 18.12.6.
|
|
18
|
+
|
|
19
|
+
## [7.0.1-omp.2] - 2026-10-24
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **Brainstorming asks before building a fully specified request that leaves a visible choice open.** A request that names every detail is no longer a quick task when doing it means choosing something the person would see that the request leaves open (a format, a default, wording, what happens on bad input). In an A/B run on omp 18.12.6 in a scratch Python todo app, with memory and the advisor off, "add an `export` command that writes `todos.csv` with columns id, text, done, due…" was built straight away on `main`, without approval, in 6 of 8 runs with 7.0.1-omp.1's text and 0 of 8 with this one; all 8 asked who or what will read the file before building anything. That is the one request the rule was written against. On requests it was not written against, both texts behaved the same in 5 of 5 runs each: three fully settled edits (rename a function, change the JSON indent, add a line to `.gitignore`) were done straight away, and an `--sort` option and an `import` command were asked about before building. A typo fix stayed a quick task and a new `count` command still took the small-change path (a branch, one commit, test first, no design doc) with either text.
|
|
24
|
+
- **Each question asks one thing, with any reason before it.** In the same run, first messages that asked instead of building put two asks into their question in 7 of 17 with the old text and 3 of 23 with this one, by a rough automatic count; one of those 3 is an either/or question. An explanation came after the question in 1 of 17 old messages and 0 of 23 new ones.
|
|
25
|
+
|
|
9
26
|
## [7.0.1-omp.1] - 2026-10-24
|
|
10
27
|
|
|
11
28
|
Synced to upstream [v7.0.1](https://github.com/obra/superpowers/blob/v7.0.1/RELEASE-NOTES.md).
|
|
@@ -126,7 +143,9 @@ First release, synced to upstream [v6.4.2](https://github.com/obra/superpowers/b
|
|
|
126
143
|
- The fork's rewritten subagent-driven-development text invokes its helper scripts through `bash` as well, so a package extractor that drops exec bits cannot break them.
|
|
127
144
|
- `sdd-final-reviewer` carries upstream's new review rules from `code-reviewer.md`, the template it replaces in SDD's final review: the spec is a vision document (behavior it is silent on is graded by what a reasonable person expects), and a "Declined to judge" section that the controller rules on and ledgers like a plan conflict.
|
|
128
145
|
|
|
129
|
-
[Unreleased]: https://github.com/LoneExile/omp-superpowers/compare/v7.0.1-omp.
|
|
146
|
+
[Unreleased]: https://github.com/LoneExile/omp-superpowers/compare/v7.0.1-omp.3...HEAD
|
|
147
|
+
[7.0.1-omp.3]: https://github.com/LoneExile/omp-superpowers/releases/tag/v7.0.1-omp.3
|
|
148
|
+
[7.0.1-omp.2]: https://github.com/LoneExile/omp-superpowers/releases/tag/v7.0.1-omp.2
|
|
130
149
|
[7.0.1-omp.1]: https://github.com/LoneExile/omp-superpowers/releases/tag/v7.0.1-omp.1
|
|
131
150
|
[7.0.0-omp.4]: https://github.com/LoneExile/omp-superpowers/releases/tag/v7.0.0-omp.4
|
|
132
151
|
[7.0.0-omp.3]: https://github.com/LoneExile/omp-superpowers/releases/tag/v7.0.0-omp.3
|
package/README.md
CHANGED
|
@@ -1,22 +1,44 @@
|
|
|
1
1
|
# omp-superpowers
|
|
2
2
|
|
|
3
|
-
[obra/superpowers](https://github.com/obra/superpowers) adapted for **omp (Oh My Pi)**.
|
|
3
|
+
[obra/superpowers](https://github.com/obra/superpowers), adapted for **omp (Oh My Pi)**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Superpowers gives your coding agent a way of working: it talks an idea through with you, writes a plan, builds it task by task with fresh subagents, reviews the work, and wraps up the branch. This fork keeps those skills and makes them fit omp.
|
|
6
|
+
|
|
7
|
+
## Why a fork
|
|
8
|
+
|
|
9
|
+
Upstream ships a Pi/omp compatibility layer, and on omp it is wrong:
|
|
10
|
+
|
|
11
|
+
- It tells the agent there is no subagent tool and no todo tool. omp has both.
|
|
12
|
+
- Its *Model Selection* rules use a `model:` field that the omp `task` tool does not have. Under those rules every subagent silently inherits the slowest configured model, with the widest tool set. In a real 157-subagent session, that was where most of the wall-clock time went.
|
|
6
13
|
|
|
7
14
|
This fork keeps the skills and fixes the omp side:
|
|
8
15
|
|
|
9
|
-
-
|
|
10
|
-
- **
|
|
11
|
-
- subagent-driven-development is rewritten around them
|
|
12
|
-
-
|
|
16
|
+
- **The tool mapping tells the truth** about `task`, `todo` and `read`/`grep`/`glob`.
|
|
17
|
+
- **Five omp agents** (`agents/sdd-*.md`) give every subagent-driven-development seat its own model, thinking level and tool set.
|
|
18
|
+
- **subagent-driven-development is rewritten around them:** a three-round fix loop, structured reviewer output, independent tasks in parallel worktrees, and a task review only where a task's risk earns it.
|
|
19
|
+
- **Fewer stops for approval.** A small change skips the design document, plan and subagents, and a project asks for one approval of design, plan and execution method together.
|
|
13
20
|
|
|
14
|
-
##
|
|
21
|
+
## Get started
|
|
22
|
+
|
|
23
|
+
Install it:
|
|
15
24
|
|
|
16
25
|
```bash
|
|
17
26
|
omp plugin install npm:@loneexile/omp-superpowers
|
|
18
27
|
```
|
|
19
28
|
|
|
29
|
+
Check that it loaded. Your `task` tool's roster should now include the five `sdd-*` agents:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
omp -p --no-session --no-skills --model anthropic/claude-haiku-4-5 \
|
|
33
|
+
'List the agent type names your `task` tool offers, comma-separated, nothing else.'
|
|
34
|
+
# scout, reviewer, security-reviewer, sonic, task, sdd-implementer, sdd-reviewer, sdd-rereviewer, sdd-escalation-implementer, sdd-final-reviewer
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
That's all. The skills drive themselves once loaded: start a new omp session and ask for what you want to build.
|
|
38
|
+
|
|
39
|
+
<details>
|
|
40
|
+
<summary><b>Versions, upgrading and other ways to install</b></summary>
|
|
41
|
+
|
|
20
42
|
Releases are versioned `<upstream version>-omp.<n>`: `6.4.2-omp.1` is upstream v6.4.2 plus this fork's first iteration on it. [CHANGELOG.md](CHANGELOG.md) lists each release. To move to another one, uninstall and install it pinned:
|
|
21
43
|
|
|
22
44
|
```bash
|
|
@@ -24,23 +46,34 @@ omp plugin uninstall @loneexile/omp-superpowers
|
|
|
24
46
|
omp plugin install npm:@loneexile/omp-superpowers@<version>
|
|
25
47
|
```
|
|
26
48
|
|
|
27
|
-
|
|
49
|
+
**After an upgrade, restart omp.** Agent definitions are read **per dispatch**, so a reinstall takes effect on the next `task` call in a running session. The injected tool mapping and the skill catalog are read at process start, so they need the restart. The bootstrap is injected at the start of each session, including `/new`, `/resume` and `/fork`, until that session's first agent run ends, and again after compaction. Main session only; subagents never get it.
|
|
28
50
|
|
|
29
|
-
|
|
51
|
+
**Unreleased `main`** installs from GitHub under the same plugin name, pinned to a commit: `omp plugin install github:LoneExile/omp-superpowers#<sha>`.
|
|
30
52
|
|
|
31
|
-
|
|
53
|
+
**Coming from before 6.4.2-omp.1?** Those installs used the plugin name `superpowers`; run `omp plugin uninstall superpowers` before installing this package.
|
|
32
54
|
|
|
33
|
-
|
|
34
|
-
omp -p --no-session --no-skills --model anthropic/claude-haiku-4-5 \
|
|
35
|
-
'List the agent type names your `task` tool offers, comma-separated, nothing else.'
|
|
36
|
-
# scout, reviewer, security-reviewer, sonic, task, sdd-implementer, sdd-reviewer, sdd-rereviewer, sdd-escalation-implementer, sdd-final-reviewer
|
|
37
|
-
```
|
|
55
|
+
**Marketplace or `--plugin-dir` installs.** npm and `github:` installs keep each seat's model. For a marketplace or `--plugin-dir` install of the repo root, the repo carries `.omp-plugin/plugin.json`: omp 18.4.10's agent discovery treats a root that has `.claude-plugin/plugin.json` as Claude dialect, and drops every agent's `model:` line, unless that file is present. This was read from omp's source; a marketplace install has not been exercised.
|
|
38
56
|
|
|
39
|
-
|
|
57
|
+
</details>
|
|
40
58
|
|
|
41
|
-
##
|
|
59
|
+
## How work flows
|
|
42
60
|
|
|
43
|
-
|
|
61
|
+
How much process a request gets depends on its size:
|
|
62
|
+
|
|
63
|
+
```mermaid
|
|
64
|
+
flowchart TD
|
|
65
|
+
R["your request"] --> B["brainstorming: what do you actually want?"]
|
|
66
|
+
B -->|"a quick, clear task"| Q["done right away"]
|
|
67
|
+
B -->|"a small change"| S["you approve it in chat; the session builds it on a branch, test first, one commit"]
|
|
68
|
+
B -->|"a project"| D["a written design"]
|
|
69
|
+
D --> P["writing-plans: the plan, then one approval of design, plan and method"]
|
|
70
|
+
P -->|"subagents"| SDD["subagent-driven-development"]
|
|
71
|
+
P -->|"Native"| EP["executing-plans: the session does every task itself"]
|
|
72
|
+
SDD --> F["finishing-a-development-branch: merge, PR or discard"]
|
|
73
|
+
EP --> F
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The usual path, skill by skill:
|
|
44
77
|
|
|
45
78
|
1. `read skill://brainstorming` — turn an idea into a design. A small change stops here: after you approve it in chat, the session builds it itself, test first, and commits once
|
|
46
79
|
2. `read skill://writing-plans` — produce `docs/plans/<date>-<name>.md`, pick the execution method, and ask once for approval of the design, the plan and the method together
|
|
@@ -49,9 +82,16 @@ The skills drive themselves once loaded. The usual path:
|
|
|
49
82
|
|
|
50
83
|
On omp the agent invokes a skill by reading it (`read skill://<name>`); you can also invoke one explicitly with `/skill:<name>`.
|
|
51
84
|
|
|
52
|
-
|
|
85
|
+
<details>
|
|
86
|
+
<summary><b>Vibe mode</b></summary>
|
|
87
|
+
|
|
88
|
+
After `/vibe` the session is a director of `fast`/`good` workers and has no `task`, `bash` or file-writing tool, so it cannot run subagent-driven-development or executing-plans itself. Both skills tell it to hand the whole run to one `good` worker, which dispatches the `sdd-*` seats through its own `task` tool. Each worker brief names the tests to run, because omp 18.4.12 workers skip them otherwise. Vibe refuses `/move` and `/wt`, so create the worktree and `/move` into it first; for a long plan set `task.softRequestBudget: 0`. Details are in the *Vibe mode* section of [`pi-tools.md`](skills/using-superpowers/references/pi-tools.md).
|
|
53
89
|
|
|
54
|
-
|
|
90
|
+
</details>
|
|
91
|
+
|
|
92
|
+
## Running a plan with subagents
|
|
93
|
+
|
|
94
|
+
subagent-driven-development hands each task to a fresh implementer, reviews it where its risk calls for that, and records every step in a ledger, so a long run can pick up where it stopped. Per task:
|
|
55
95
|
|
|
56
96
|
```mermaid
|
|
57
97
|
flowchart TD
|
|
@@ -82,7 +122,7 @@ flowchart TD
|
|
|
82
122
|
|
|
83
123
|
Blue nodes are the five omp agents this fork ships. A reviewer that cannot read its package yields the `package_gap` verdict value (with what it tried) instead of inventing one, and the controller regenerates and re-dispatches.
|
|
84
124
|
|
|
85
|
-
### The
|
|
125
|
+
### The five seats
|
|
86
126
|
|
|
87
127
|
| Seat | agent | shipped default · thinking | falls back to | tools |
|
|
88
128
|
|---|---|---|---|---|
|
|
@@ -92,15 +132,44 @@ Blue nodes are the five omp agents this fork ships. A reviewer that cannot read
|
|
|
92
132
|
| fix round 3 / ruled strongest-tier task | `sdd-escalation-implementer` | claude-opus-5-5 · max | `@slow` | same as implementer |
|
|
93
133
|
| final whole-branch review (subagent-driven or Native) | `sdd-final-reviewer` | claude-opus-5-5 · max | `@slow` | read, grep, glob, bash, lsp, ast_grep |
|
|
94
134
|
|
|
135
|
+
The shipped defaults are Anthropic: sonnet for the seats that run on every task, opus for the two that run once per plan or once per stuck task. The tiers are a **thinking ladder** as much as a model ladder — re-reviews reason at `low`, escalation and the final review at `max`.
|
|
136
|
+
|
|
95
137
|
`lsp` and `ast_grep` are listed for the seats that benefit, but omp only activates them in subagents when `task.enableLsp` / `astGrep.enabled` are on (both default off).
|
|
96
138
|
|
|
139
|
+
<details>
|
|
140
|
+
<summary><b>Which model a seat actually runs on</b></summary>
|
|
141
|
+
|
|
97
142
|
omp takes the first list entry whose provider has credentials. If the pin has none, the seat runs on your `modelRoles.task` / `modelRoles.slow` model at that role's own level. An unset `@task` drops out, and the seat then silently runs on the controller's model; an unset `@slow` expands to omp's built-in strong-model ranking. The list is also the retry chain on rate-limit and usage-limit errors, gated by `retry.modelFallback` (default on); there is no switch on context overflow. Turn on `task.showResolvedModelBadge`, or read `session_init.resolvedModel` in a subagent transcript, to see what actually ran.
|
|
98
143
|
|
|
99
|
-
|
|
144
|
+
</details>
|
|
145
|
+
|
|
146
|
+
<details>
|
|
147
|
+
<summary><b>What the reviewer seats can and can't do</b></summary>
|
|
100
148
|
|
|
101
149
|
The two reviewer seats have no `bash`, `edit`, or filesystem `write`: the review package (`git diff -U10` written to a file) is their whole view of the change, and they return a structured result (`spec_compliance`, `task_quality`, `findings[]`, `cannot_verify[]`; `finding_verdicts[]`, `new_breakage[]`, `round_verdict`) plus `package_gap` when they could not read the package. Note the honest boundary: an agent's `tools:` list limits built-in tools only. Extension tools and MCP tools (mounted as `xd://` devices and run through a device-only `write`) still attach to every subagent; memory tools attach only when the agent's `tools:` list names them. On omp 18.4.10 a read/grep/glob reviewer ran a shell command through an MCP device. Read-only is by instruction, not a sandbox.
|
|
102
150
|
|
|
103
|
-
|
|
151
|
+
</details>
|
|
152
|
+
|
|
153
|
+
## Changing models (no file edits)
|
|
154
|
+
|
|
155
|
+
Set `task.agentModelOverrides` in `~/.omp/agent/config.yml`, or use `/agents` in any session (it edits the same map). It applies on the next dispatch; delete a line to fall back to the agent file.
|
|
156
|
+
|
|
157
|
+
Example — every seat on one flat-rate model, mapped onto that model's own thinking ladder:
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
task:
|
|
161
|
+
agentModelOverrides:
|
|
162
|
+
sdd-implementer: opencode-go/deepseek-v4.1-flash:high
|
|
163
|
+
sdd-reviewer: opencode-go/deepseek-v4.1-flash:high
|
|
164
|
+
sdd-rereviewer: opencode-go/deepseek-v4.1-flash:low
|
|
165
|
+
sdd-escalation-implementer: opencode-go/deepseek-v4.1-flash:max
|
|
166
|
+
sdd-final-reviewer: opencode-go/deepseek-v4.1-flash:max
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Use the exact catalog id and a level the model actually offers.** `omp models ls <provider>` shows each model's ladder. A level that is not on it is silently clamped to the nearest valid one — `deepseek-v4.1-flash` offers only `low, high, max`, so `:medium` would run at `low` and `:xhigh` at `high`, collapsing the ladder without any error. Check `session_init.resolvedModel` in a subagent transcript if in doubt: it shows the level that actually ran. Catalog ids also get renamed (this one was `deepseek-flash` a day earlier, and the old string now matches an empty placeholder row).
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary><b>How omp resolves a seat's model and thinking level</b></summary>
|
|
104
173
|
|
|
105
174
|
omp resolves each seat's model and thinking level in a fixed order. The override map is the layer meant for you:
|
|
106
175
|
|
|
@@ -119,25 +188,10 @@ flowchart LR
|
|
|
119
188
|
class M1 you
|
|
120
189
|
```
|
|
121
190
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Example — every seat on one flat-rate model, mapped onto that model's own thinking ladder:
|
|
125
|
-
|
|
126
|
-
```yaml
|
|
127
|
-
task:
|
|
128
|
-
agentModelOverrides:
|
|
129
|
-
sdd-implementer: opencode-go/deepseek-v4.1-flash:high
|
|
130
|
-
sdd-reviewer: opencode-go/deepseek-v4.1-flash:high
|
|
131
|
-
sdd-rereviewer: opencode-go/deepseek-v4.1-flash:low
|
|
132
|
-
sdd-escalation-implementer: opencode-go/deepseek-v4.1-flash:max
|
|
133
|
-
sdd-final-reviewer: opencode-go/deepseek-v4.1-flash:max
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
**Use the exact catalog id and a level the model actually offers.** `omp models ls <provider>` shows each model's ladder. A level that is not on it is silently clamped to the nearest valid one — `deepseek-v4.1-flash` offers only `low, high, max`, so `:medium` would run at `low` and `:xhigh` at `high`, collapsing the ladder without any error. Check `session_init.resolvedModel` in a subagent transcript if in doubt: it shows the level that actually ran. Catalog ids also get renamed (this one was `deepseek-flash` a day earlier, and the old string now matches an empty placeholder row).
|
|
137
|
-
|
|
138
|
-
Measured on a real fix-round re-review with identical inputs: a grok-4.6 seat took 9.7 min / 4 turns, sonnet-5 about 50 s / 1 turn, the DeepSeek flash seat 100 s / 4 turns — same verdict, full structured result, all three.
|
|
191
|
+
</details>
|
|
139
192
|
|
|
140
|
-
|
|
193
|
+
<details>
|
|
194
|
+
<summary><b>Rules that are easy to get wrong</b></summary>
|
|
141
195
|
|
|
142
196
|
- A **bare model** (`anthropic/claude-haiku-4-5`) keeps the agent file's own `thinkingLevel`. Add `:level` (`…:high`) to change reasoning too.
|
|
143
197
|
- **Delete a line** to fall back to the agent file's default for that seat. Overrides apply on the next dispatch — no restart.
|
|
@@ -146,7 +200,11 @@ Rules that are easy to get wrong:
|
|
|
146
200
|
- `effort` on a dispatch (when `task.enableEffort` is on) accepts only `"lo"`, `"med"`, `"hi"`. `"hi"` maps to the model's top supported level, capped by `task.maxEffort`; SDD uses `effort: "hi"` for high-risk task reviews, and for escalation only when a host override lowers that seat.
|
|
147
201
|
- Discovery-only model ids (the OpenCode Go catalog, for example) accept `:level` in config and in overrides but not on the `--model` CLI flag.
|
|
148
202
|
|
|
149
|
-
|
|
203
|
+
Measured on a real fix-round re-review with identical inputs: a grok-4.6 seat took 9.7 min / 4 turns, sonnet-5 about 50 s / 1 turn, the DeepSeek flash seat 100 s / 4 turns — same verdict, full structured result, all three.
|
|
204
|
+
|
|
205
|
+
</details>
|
|
206
|
+
|
|
207
|
+
## Settings worth knowing
|
|
150
208
|
|
|
151
209
|
| setting | why |
|
|
152
210
|
|---|---|
|
|
@@ -158,10 +216,15 @@ Rules that are easy to get wrong:
|
|
|
158
216
|
|
|
159
217
|
## What changed from upstream
|
|
160
218
|
|
|
161
|
-
|
|
219
|
+
In short: the omp extension and `pi-tools.md` describe omp's real tools; five `sdd-*` agents are new; subagent-driven-development, executing-plans, writing-plans and brainstorming are reworked as described above; requesting-code-review, using-git-worktrees and finishing-a-development-branch get small edits; and specs and plans live in `docs/specs/` and `docs/plans/`.
|
|
220
|
+
|
|
221
|
+
<details>
|
|
222
|
+
<summary><b>File by file</b></summary>
|
|
223
|
+
|
|
224
|
+
- `.pi/extensions/superpowers.ts` — the injected mapping names `task`, `todo`, the `sdd-*` roster, and the no-`model:`-field rule; it also re-arms on `session_switch`, skips subagent sessions, and ignores an `agent_end` that will auto-continue; it tells a dispatching session to name the checks each subagent must run, since omp 18.4.12 tells subagents to leave builds, tests and smoke runs to the main agent unless their assignment explicitly instructs them; its last paragraph points a vibe-mode director (tools include `vibe_spawn` but not `task`) at the *Vibe mode* section of `pi-tools.md`; after a compaction, the re-injected bootstrap also names the superpowers skills read before it and the last SDD ledger path, read from the session branch so it holds for any compaction method and after `omp -c`, and `session.compacting` hands the same lines to the summarizer
|
|
162
225
|
- `.omp-plugin/plugin.json` — new. Marks the repo root as an omp-native plugin so a marketplace or `--plugin-dir` install keeps each agent's `model:` line
|
|
163
226
|
- `skills/using-superpowers/references/pi-tools.md` — same, as the reference doc; it also gains a *Checks* subsection (the 18.4.12 subagent hand-off rule, and why every dispatch names its checks) and a *Vibe mode* section: what a director keeps and lacks, how skill actions map onto `vibe_*` and workers, and the worktree and request-budget limits
|
|
164
|
-
- `skills/brainstorming/` — a defined small-change path: after the in-chat approval the session builds it itself on a branch: the full suite before changing anything, test first, the covering tests and the suite again, then one commit of only its own files and hunks, with no design document, plan or subagents (a new behavior such as a `--quiet` flag can be small; security, auth, concurrency, money, migrations, changes one revert cannot undo, new config files or stored formats, changes to existing behavior, new interfaces other code builds on and new dependencies never are, and none of them takes the quick-task route however complete the request); a playback rides along with the next question instead of waiting for its own answer; for software, the plan is written right after the builder check so the design and the plan get one approval. Of upstream v7.0.1's retune it keeps reading the project first, the new first message and the sharper questions; the approaches ride with the last playback chunk, whose one question is the pick, instead of going out in a message of their own; upstream's short design doc and plan for every small change are not taken
|
|
227
|
+
- `skills/brainstorming/` — a defined small-change path: after the in-chat approval the session builds it itself on a branch: the full suite before changing anything, test first, the covering tests and the suite again, then one commit of only its own files and hunks, with no design document, plan or subagents (a new behavior such as a `--quiet` flag can be small; security, auth, concurrency, money, migrations, changes one revert cannot undo, new config files or stored formats, changes to existing behavior, new interfaces other code builds on and new dependencies never are, and none of them takes the quick-task route however complete the request); a request is a quick task only if doing it leaves no choice the person would see (a format, a default, wording, bad input) for the agent to make; each question asks one thing, with any reason before it; a playback rides along with the next question instead of waiting for its own answer; for software, the plan is written right after the builder check so the design and the plan get one approval. Of upstream v7.0.1's retune it keeps reading the project first, the new first message and the sharper questions; the approaches ride with the last playback chunk, whose one question is the pick, instead of going out in a message of their own; upstream's short design doc and plan for every small change are not taken
|
|
165
228
|
- `agents/sdd-*.md` — new. Each seat's `model:` is a pin plus a role fallback (`@task` or `@slow`), and all set `readSummarize: false`. `sdd-final-reviewer` reviews the whole branch for both ways of running a plan; after subagent-driven-development it does the task review's work on every task left to it (`review at final`) before the seams. It reads `requesting-code-review/code-reviewer.md` at run time and applies its What to Check, Calibration, severity definitions and Critical Rules, while carrying upstream's vision-document and Declined-to-judge rules in its own body; a crash or lost data on user input is always a finding, never a Declined-to-judge line. Descriptions name roles, never models
|
|
166
229
|
- `skills/subagent-driven-development/` — *Model Selection* → *Agent Selection*; fix-loop cap 5 → 3 with a round-3 escalation seat; a proven-trivial-fix route that replaces a re-review with a one-command proof; the pre-flight scan builds a review list (plan-marked or ruled high-risk tasks get a task review, the rest get the controller's own covering-test run and the final review) and waves (tasks with no shared file or interface run in parallel, up to three, each in its own `omp worktree add` worktree with the project's install step re-run there, merged back with `--no-ff` after their covering tests pass on the merged tree; a task that still will not merge after round 3 stops the run); Setup creates the approved branch in this checkout instead of a worktree; resume reads each task's last ledger line, and treats a wave task as merged only when its branch has commits past BASE; the scripts directory resolves via `realpath skill://subagent-driven-development/scripts`; fix rounds resume the implementer with `write agent://<id>` (id ledgered) and full results are read at `agent://<id>`; task review scales with risk through `effort: "hi"`; the controller checks reviewer results; templates show omp's real `{ context, tasks: [{ agent, task, solutionSpace }] }` wire shape and the reviewers' structured fields; one omp paragraph for vibe mode, where a director (no `task` or `bash`) hands the whole run to one `good` worker that dispatches the seats itself. Upstream v7.0.1's `references/` is deleted: it holds upstream's own fix loop (5 rounds), final review and resume text, and nothing in this SKILL.md points to it
|
|
167
230
|
- `skills/executing-plans/` — the description, *Why inline*, *When to Use* and the "Prefer subagent-driven-development" paragraph say the partner approved inline execution at the handoff and that SDD reviews per task only where a plan marks it; Setup creates the approved branch in this checkout; a ledger with `Wave` lines resumes under SDD. Additive omp paragraphs: in *Final Review*, the `task` tool has no `model:` field, so the final review goes to `sdd-final-reviewer` (its model is what the host maps that agent to), told that no task was reviewed; it also resolves the scripts directory with `realpath` and reads full results at `agent://<id>`; one more for vibe mode, where a director hands the whole run to one `good` worker
|
|
@@ -176,11 +239,14 @@ Rules that are easy to get wrong:
|
|
|
176
239
|
- Spec and plan paths — `docs/specs/` and `docs/plans/` instead of upstream's `docs/superpowers/specs/` and `docs/superpowers/plans/`: brainstorming's *Where it goes*, writing-plans' save path and handoff lines, and the example plan paths in executing-plans, subagent-driven-development and requesting-code-review. `.superpowers/` (the SDD workspace, brainstorm companion files) is unchanged. `scripts/check-npm-package.sh` fails if a shipped file names `docs/superpowers/`
|
|
177
240
|
- `CHANGELOG.md`, `.github/workflows/` (CI, npm release), `scripts/check-npm-package.sh` — new
|
|
178
241
|
|
|
242
|
+
</details>
|
|
243
|
+
|
|
179
244
|
Everything else is upstream, unmodified.
|
|
180
245
|
|
|
181
|
-
##
|
|
246
|
+
## Maintaining the fork
|
|
182
247
|
|
|
183
|
-
|
|
248
|
+
<details>
|
|
249
|
+
<summary><b>Syncing with upstream</b></summary>
|
|
184
250
|
|
|
185
251
|
```bash
|
|
186
252
|
git fetch upstream --tags
|
|
@@ -188,13 +254,16 @@ git rebase upstream/main
|
|
|
188
254
|
git push --force-with-lease origin main
|
|
189
255
|
```
|
|
190
256
|
|
|
191
|
-
Expect conflicts in `skills/subagent-driven-development/`, `skills/brainstorming/`, `skills/writing-plans/`, `skills/executing-plans/`, `skills/requesting-code-review/SKILL.md`, `skills/finishing-a-development-branch/SKILL.md`, `pi-tools.md`, `README.md`, and `package.json` whenever upstream touches them — this fork rewrites those files rather than appending to them (README.md is never a partial conflict). A sync that takes upstream's side of executing-plans or requesting-code-review brings back "review after every task" text that contradicts subagent-driven-development's review list: keep the fork's lines. In `package.json` keep the fork's identity and set `version` to `<new upstream version>-omp.1`: CI's package check fails until the version's base matches the upstream version in `.claude-plugin/plugin.json`. `agents/`, the extension's mapping paragraph, and the omp blocks in `using-git-worktrees` are additive.
|
|
257
|
+
Expect conflicts in `skills/subagent-driven-development/`, `skills/brainstorming/`, `skills/writing-plans/`, `skills/executing-plans/`, `skills/requesting-code-review/SKILL.md`, `skills/finishing-a-development-branch/SKILL.md`, `pi-tools.md`, `README.md`, and `package.json` whenever upstream touches them — this fork rewrites those files rather than appending to them (README.md is never a partial conflict). A sync that takes upstream's side of executing-plans or requesting-code-review brings back "review after every task" text that contradicts subagent-driven-development's review list: keep the fork's lines. In `package.json` keep the fork's identity and set `version` to `<new upstream version>-omp.1`: CI's package check fails until the version's base matches the upstream version in `.claude-plugin/plugin.json`. `tests/brainstorm-server/server.test.js` conflicts whenever upstream edits it: keep the fork's file until upstream's `settleWatcher` waits for the client to receive its marker file's reload, then take upstream's and drop its line from What changed from upstream. `agents/`, the extension's mapping paragraph, and the omp blocks in `using-git-worktrees` are additive.
|
|
192
258
|
|
|
193
259
|
A clean rebase is not the whole sync. Upstream's edits to text this fork replaced never reach the replacement, so read upstream's diff for those files and port what still applies. The v6.4.x sync needed two: `bash scripts/...` invocations in the SDD text, and `code-reviewer.md`'s new review rules. The v7.0.1 sync took the fork's side of brainstorming and ported the retune by hand, all but its small-change gate, and deleted upstream's `skills/subagent-driven-development/references/`; when upstream edits a file there, the rebase stops on a modify/delete conflict: keep it deleted (`git rm`), then read upstream's diff of that file for rule changes to port into the fork's SDD text. Upstream edits to `code-reviewer.md`'s What to Check, Calibration, severity definitions and Critical Rules now reach `sdd-final-reviewer` without porting, because it reads the file at run time. Edits to the vision-document or Declined-to-judge sections still need porting into the agent body, which carries them itself.
|
|
194
260
|
|
|
195
261
|
The fork changes upstream's `docs/superpowers/specs` and `docs/superpowers/plans` lines in brainstorming, writing-plans, executing-plans, subagent-driven-development and requesting-code-review. When upstream edits around one of them, `-X theirs` keeps the fork's whole conflicting hunk, so read upstream's diff of those lines and port the rest of the hunk. New upstream text naming `docs/superpowers/` fails `check-npm-package.sh` until it says `docs/specs/` or `docs/plans/`.
|
|
196
262
|
|
|
197
|
-
|
|
263
|
+
</details>
|
|
264
|
+
|
|
265
|
+
<details>
|
|
266
|
+
<summary><b>Releasing</b></summary>
|
|
198
267
|
|
|
199
268
|
1. Set `version` in `package.json`, move CHANGELOG.md's *Unreleased* entries under that version, commit, push, and wait for CI.
|
|
200
269
|
2. Publish a GitHub release for the tag `v<version>`; the [release workflow](.github/workflows/release.yml) publishes it to npm through Trusted Publishing, with provenance:
|
|
@@ -205,9 +274,14 @@ awk -v h="## [$v]" 'index($0, h) == 1 {f = 1; next} f && /^(## )?\[/ {exit} f' C
|
|
|
205
274
|
gh release create "v$v" --target main --title "v$v" --notes-file /tmp/notes.md
|
|
206
275
|
```
|
|
207
276
|
|
|
208
|
-
|
|
277
|
+
</details>
|
|
278
|
+
|
|
279
|
+
<details>
|
|
280
|
+
<summary><b>Checking a new omp version</b></summary>
|
|
281
|
+
|
|
282
|
+
Before trusting a new omp release, re-check the harness facts this fork depends on — against the **running binary**, not an npm source tree that may lag it. `~/.bun/install/global/node_modules/@oh-my-pi/pi-coding-agent/src` routinely lags `omp --version` (a 17.4.2 tree sat beside an 18.1.17 binary while this README was written, and the isolation setting had been renamed in between). The fork was last verified against omp 18.4.10; its vibe-mode text and the subagent check rule were re-checked against 18.4.12, and the `task.isolation` notes against 18.11.0 and again, live, on 18.12.6. To read the exact running version's source, pack it into a temp dir: `cd "$(mktemp -d)" && npm pack @oh-my-pi/pi-coding-agent@$(omp --version | cut -d/ -f2) && tar xzf *.tgz` (source under `package/src`). The live oracles are `omp config list --json` (every setting and its default), the `task` tool's own description in a session (agent roster, item fields), a `session_init.resolvedModel` line in a subagent transcript (what actually resolved), and `grep -a` on the binary for an exact string when you need to know whether a code path exists.
|
|
209
283
|
|
|
210
|
-
|
|
284
|
+
</details>
|
|
211
285
|
|
|
212
286
|
## License
|
|
213
287
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loneexile/omp-superpowers",
|
|
3
|
-
"version": "7.0.1-omp.
|
|
3
|
+
"version": "7.0.1-omp.3",
|
|
4
4
|
"description": "obra/superpowers adapted for Oh My Pi (omp): a truthful task/todo tool mapping and five subagent-driven-development agents, each with its own model, thinking level, and tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -20,9 +20,12 @@ Before you reply, ask yourself: what do I know about what they want, and
|
|
|
20
20
|
why?
|
|
21
21
|
|
|
22
22
|
- **Everything that matters is in the request** ("make the icon cornflower
|
|
23
|
-
blue"). This is a quick, clear task. Do it, and say what you did.
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
blue"). This is a quick, clear task. Do it, and say what you did. If
|
|
24
|
+
doing it means making choices they would see that the request leaves
|
|
25
|
+
open (a format, a default, wording, what happens on bad input), so you'd
|
|
26
|
+
have to tell them what you chose, it isn't a quick task: start the
|
|
27
|
+
conversation. Nothing on the never-small list (Size the Work) is a quick
|
|
28
|
+
task, however complete the request.
|
|
26
29
|
- **Something non-trivial is missing.** Start the conversation.
|
|
27
30
|
|
|
28
31
|
## Look Before You Ask
|
|
@@ -76,11 +79,12 @@ That's the whole message.
|
|
|
76
79
|
|
|
77
80
|
## The Conversation
|
|
78
81
|
|
|
79
|
-
Each message ends with one question: a single sentence
|
|
80
|
-
example answers hanging off it.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
Each message ends with one question: a single sentence that asks one
|
|
83
|
+
thing, with no list of example answers hanging off it. Anything that
|
|
84
|
+
explains the question, like why you're asking, goes before it. Use plain
|
|
85
|
+
language, pitched just a little above where your human partner is. Match
|
|
86
|
+
their vocabulary; never use process jargon. You never need to quote this
|
|
87
|
+
skill to your human partner.
|
|
84
88
|
|
|
85
89
|
Be clear and concise. Lead with what matters. Avoid jargon. When you
|
|
86
90
|
report what you found, give them the most important findings and offer
|