supipowers 0.2.6 → 0.3.0

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.
Files changed (45) hide show
  1. package/package.json +21 -6
  2. package/skills/debugging/SKILL.md +54 -15
  3. package/skills/planning/SKILL.md +70 -10
  4. package/skills/receiving-code-review/SKILL.md +87 -0
  5. package/skills/tdd/SKILL.md +83 -0
  6. package/skills/verification/SKILL.md +54 -0
  7. package/src/commands/config.ts +53 -23
  8. package/src/commands/plan.ts +96 -31
  9. package/src/commands/qa.ts +150 -29
  10. package/src/commands/release.ts +1 -1
  11. package/src/commands/review.ts +2 -2
  12. package/src/commands/run.ts +52 -2
  13. package/src/commands/update.ts +2 -2
  14. package/src/discipline/debugging.ts +57 -0
  15. package/src/discipline/receiving-review.ts +65 -0
  16. package/src/discipline/tdd.ts +77 -0
  17. package/src/discipline/verification.ts +68 -0
  18. package/src/git/branch-finish.ts +101 -0
  19. package/src/git/worktree.ts +119 -0
  20. package/src/index.ts +11 -2
  21. package/src/lsp/detector.ts +2 -2
  22. package/src/orchestrator/agent-prompts.ts +282 -0
  23. package/src/orchestrator/dispatcher.ts +150 -1
  24. package/src/orchestrator/prompts.ts +17 -31
  25. package/src/planning/plan-reviewer.ts +49 -0
  26. package/src/planning/plan-writer-prompt.ts +173 -0
  27. package/src/planning/prompt-builder.ts +178 -0
  28. package/src/planning/spec-reviewer.ts +43 -0
  29. package/src/qa/phases/discovery.ts +34 -0
  30. package/src/qa/phases/execution.ts +65 -0
  31. package/src/qa/phases/matrix.ts +41 -0
  32. package/src/qa/phases/reporting.ts +71 -0
  33. package/src/qa/session.ts +104 -0
  34. package/src/storage/qa-sessions.ts +83 -0
  35. package/src/storage/specs.ts +36 -0
  36. package/src/types.ts +70 -0
  37. package/src/visual/companion.ts +115 -0
  38. package/src/visual/prompt-instructions.ts +102 -0
  39. package/src/visual/scripts/frame-template.html +201 -0
  40. package/src/visual/scripts/helper.js +88 -0
  41. package/src/visual/scripts/index.js +148 -0
  42. package/src/visual/scripts/package.json +10 -0
  43. package/src/visual/scripts/start-server.sh +98 -0
  44. package/src/visual/scripts/stop-server.sh +21 -0
  45. package/src/visual/types.ts +16 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * TDD enforcement instructions for sub-agent prompts.
3
+ * Matches superpowers' test-driven-development skill depth.
4
+ */
5
+ export function buildTddInstructions(): string {
6
+ return [
7
+ "## Test-Driven Development",
8
+ "",
9
+ "### Iron Law",
10
+ "",
11
+ "NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST.",
12
+ "",
13
+ "Write code before the test? Delete it. Start over.",
14
+ "",
15
+ "### Red-Green-Refactor Cycle",
16
+ "",
17
+ "**RED — Write failing test:**",
18
+ "- One behavior per test, clear name, real code (no mocks unless unavoidable)",
19
+ "- Watch it fail. MANDATORY. Never skip.",
20
+ "- Confirm: test fails (not errors), failure message is expected, fails because feature is missing",
21
+ "- Test passes? You're testing existing behavior. Fix the test.",
22
+ "",
23
+ "**GREEN — Write the simplest code to pass:**",
24
+ "- Minimal, simplest code that makes the test pass",
25
+ "- Don't add features, refactor other code, or improve beyond the test",
26
+ "- Watch it pass. MANDATORY.",
27
+ "- Confirm: test passes, other tests still pass, output pristine",
28
+ "- Test fails? Fix code, not test. Other tests fail? Fix now.",
29
+ "",
30
+ "**REFACTOR — Clean up (after green only):**",
31
+ "- Remove duplication, improve names, extract helpers",
32
+ "- Keep tests green. Don't add behavior.",
33
+ "",
34
+ "### Verification Checklist",
35
+ "",
36
+ "Before marking work complete:",
37
+ "- Every new function/method has a test",
38
+ "- Watched each test fail before implementing",
39
+ "- Each test failed for expected reason (feature missing, not typo)",
40
+ "- Wrote minimal code to pass each test",
41
+ "- All tests pass with pristine output",
42
+ "- Tests use real code (mocks only if unavoidable)",
43
+ "- Edge cases and errors covered",
44
+ "",
45
+ "### Red Flags — STOP and Start Over",
46
+ "",
47
+ "- Code before test",
48
+ "- Test after implementation",
49
+ "- Test passes immediately",
50
+ "- Can't explain why test failed",
51
+ "- Tests added later",
52
+ "- Rationalizing \"just this once\"",
53
+ "",
54
+ "### Testing Anti-Patterns",
55
+ "",
56
+ "- Don't test mock behavior instead of real behavior",
57
+ "- Don't add test-only methods to production classes",
58
+ "- Don't mock without understanding dependencies",
59
+ "- Don't use incomplete mocks (partial data structures)",
60
+ "- Mocks are tools to isolate, not things to test",
61
+ "",
62
+ "### When Stuck",
63
+ "",
64
+ "| Problem | Solution |",
65
+ "|---------|----------|",
66
+ "| Don't know how to test | Write wished-for API. Write assertion first. Ask. |",
67
+ "| Test too complicated | Design too complicated. Simplify interface. |",
68
+ "| Must mock everything | Code too coupled. Use dependency injection. |",
69
+ "| Test setup huge | Extract helpers. Still complex? Simplify design. |",
70
+ "",
71
+ "### Bug Fix Flow",
72
+ "",
73
+ "Bug found? Write a failing test reproducing it first.",
74
+ "Follow the TDD cycle. The test proves the fix and prevents regression.",
75
+ "Never fix bugs without a failing test.",
76
+ ].join("\n");
77
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Verification-before-completion instructions for sub-agent prompts.
3
+ * Matches superpowers' verification-before-completion skill depth.
4
+ */
5
+ export function buildVerificationInstructions(): string {
6
+ return [
7
+ "## Verification Before Completion",
8
+ "",
9
+ "### Iron Law",
10
+ "",
11
+ "NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.",
12
+ "Evidence before assertions, always.",
13
+ "",
14
+ "### The Gate Function (Mandatory Before Any Status Claim)",
15
+ "",
16
+ "1. **IDENTIFY:** What command proves this claim?",
17
+ "2. **RUN:** Execute the FULL command (fresh, complete).",
18
+ "3. **READ:** Full output. Check exit code. Count failures.",
19
+ "4. **VERIFY:** Does output confirm the claim?",
20
+ " - If NO: State actual status with evidence.",
21
+ " - If YES: State claim WITH evidence.",
22
+ "5. **ONLY THEN:** Make the claim.",
23
+ "",
24
+ "Skip any step = lying, not verifying.",
25
+ "",
26
+ "### Common Failure Patterns",
27
+ "",
28
+ "| Claim | Requires | Not Sufficient |",
29
+ "|-------|----------|----------------|",
30
+ "| Tests pass | Test command output: 0 failures | Previous run, \"should pass\" |",
31
+ "| Build succeeds | Build command: exit 0 | Linter passing, logs look good |",
32
+ "| Bug fixed | Test original symptom: passes | Code changed, assumed fixed |",
33
+ "| Regression test works | Red-green cycle verified | Test passes once |",
34
+ "| Agent completed | VCS diff shows changes | Agent reports \"success\" |",
35
+ "| Requirements met | Line-by-line checklist | Tests passing |",
36
+ "",
37
+ "### Red Flags — STOP Before Claiming",
38
+ "",
39
+ "- Using \"should\", \"probably\", \"seems to\"",
40
+ "- Expressing satisfaction before verification (\"Great!\", \"Perfect!\", \"Done!\")",
41
+ "- About to commit/push/PR without verification",
42
+ "- Trusting agent success reports without checking",
43
+ "- Relying on partial verification",
44
+ "- Thinking \"just this once\"",
45
+ "",
46
+ "### Verification Patterns",
47
+ "",
48
+ "**Tests:**",
49
+ "- Run test command → see actual pass count → then claim",
50
+ "- Never say \"should pass now\" or \"looks correct\"",
51
+ "",
52
+ "**Regression tests (TDD red-green):**",
53
+ "- Write → Run (pass) → Revert fix → Run (MUST FAIL) → Restore → Run (pass)",
54
+ "- Never say \"I've written a regression test\" without red-green verification",
55
+ "",
56
+ "**Build:**",
57
+ "- Run build → see exit 0 → then claim",
58
+ "- Linter passing does not prove compilation",
59
+ "",
60
+ "**Requirements:**",
61
+ "- Re-read plan → create checklist → verify each → report gaps or completion",
62
+ "- Never say \"tests pass, phase complete\" without checking requirements",
63
+ "",
64
+ "**Agent delegation:**",
65
+ "- Agent reports success → check VCS diff → verify changes → report actual state",
66
+ "- Never trust agent report without independent verification",
67
+ ].join("\n");
68
+ }
@@ -0,0 +1,101 @@
1
+ export interface FinishOption {
2
+ id: "merge" | "pr" | "keep" | "discard";
3
+ label: string;
4
+ }
5
+
6
+ /** The 4 structured options for finishing a branch */
7
+ export const FINISH_OPTIONS: FinishOption[] = [
8
+ { id: "merge", label: "Merge back to base branch locally" },
9
+ { id: "pr", label: "Push and create a Pull Request" },
10
+ { id: "keep", label: "Keep the branch as-is (handle later)" },
11
+ { id: "discard", label: "Discard this work" },
12
+ ];
13
+
14
+ export interface BranchFinishPromptOptions {
15
+ branchName: string;
16
+ baseBranch: string;
17
+ worktreePath?: string;
18
+ }
19
+
20
+ /**
21
+ * Build the prompt that guides the agent through finishing a development branch.
22
+ * Follows superpowers' finishing-a-development-branch skill:
23
+ * - Verify tests pass first
24
+ * - Present exactly 4 options
25
+ * - Execute chosen option
26
+ * - Clean up worktree (conditional)
27
+ */
28
+ export function buildBranchFinishPrompt(options: BranchFinishPromptOptions): string {
29
+ const { branchName, baseBranch, worktreePath } = options;
30
+
31
+ const sections: string[] = [
32
+ "## Finish Development Branch",
33
+ "",
34
+ `Branch: \`${branchName}\` (base: \`${baseBranch}\`)`,
35
+ "",
36
+ "### Step 1: Verify tests pass",
37
+ "",
38
+ "Run the full test suite. All tests must pass before proceeding.",
39
+ "If tests fail, fix them first — do not offer options until green.",
40
+ "",
41
+ "### Step 2: Present options",
42
+ "",
43
+ "Ask the user:",
44
+ "",
45
+ "> Implementation complete. What would you like to do?",
46
+ ">",
47
+ `> 1. Merge back to \`${baseBranch}\` locally`,
48
+ "> 2. Push and create a Pull Request",
49
+ "> 3. Keep the branch as-is (handle later)",
50
+ "> 4. Discard this work",
51
+ "",
52
+ "### Option 1: Merge locally",
53
+ "",
54
+ "```bash",
55
+ `git checkout ${baseBranch}`,
56
+ "git pull",
57
+ `git merge ${branchName}`,
58
+ "# Verify tests pass on merged result",
59
+ `git branch -d ${branchName}`,
60
+ "```",
61
+ "",
62
+ "### Option 2: Push and create Pull Request",
63
+ "",
64
+ "```bash",
65
+ `git push -u origin ${branchName}`,
66
+ `gh pr create --title "<title>" --body "<summary>"`,
67
+ "```",
68
+ "",
69
+ "### Option 3: Keep as-is",
70
+ "",
71
+ `Report: "Keeping branch ${branchName}."`,
72
+ "Do NOT clean up worktree.",
73
+ "",
74
+ "### Option 4: Discard",
75
+ "",
76
+ "**Require explicit confirm before deleting.** Show what will be lost:",
77
+ "",
78
+ "```bash",
79
+ `git checkout ${baseBranch}`,
80
+ `git branch -D ${branchName}`,
81
+ "```",
82
+ ];
83
+
84
+ if (worktreePath) {
85
+ sections.push(
86
+ "",
87
+ "### Worktree cleanup",
88
+ "",
89
+ `Worktree at: \`${worktreePath}\``,
90
+ "",
91
+ "- **Options 1 and 4:** Clean up the worktree:",
92
+ " ```bash",
93
+ ` git worktree remove ${worktreePath}`,
94
+ " ```",
95
+ "- **Option 2:** Keep worktree (PR may need updates)",
96
+ "- **Option 3:** Keep worktree",
97
+ );
98
+ }
99
+
100
+ return sections.join("\n");
101
+ }
@@ -0,0 +1,119 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+
4
+ export interface ProjectSetup {
5
+ type: "node" | "rust" | "python" | "go" | "unknown";
6
+ installCommand: string | null;
7
+ testCommand: string | null;
8
+ }
9
+
10
+ /**
11
+ * Detect existing worktree directory following priority:
12
+ * .worktrees > worktrees > null
13
+ */
14
+ export function detectWorktreeDir(cwd: string): string | null {
15
+ const dotWorktrees = path.join(cwd, ".worktrees");
16
+ if (fs.existsSync(dotWorktrees)) return dotWorktrees;
17
+
18
+ const worktrees = path.join(cwd, "worktrees");
19
+ if (fs.existsSync(worktrees)) return worktrees;
20
+
21
+ return null;
22
+ }
23
+
24
+ /**
25
+ * Auto-detect project type and setup commands from project files.
26
+ */
27
+ export function detectProjectSetup(cwd: string): ProjectSetup {
28
+ if (fs.existsSync(path.join(cwd, "package.json"))) {
29
+ return { type: "node", installCommand: "npm install", testCommand: "npm test" };
30
+ }
31
+ if (fs.existsSync(path.join(cwd, "Cargo.toml"))) {
32
+ return { type: "rust", installCommand: "cargo build", testCommand: "cargo test" };
33
+ }
34
+ if (fs.existsSync(path.join(cwd, "requirements.txt"))) {
35
+ return { type: "python", installCommand: "pip install -r requirements.txt", testCommand: "pytest" };
36
+ }
37
+ if (fs.existsSync(path.join(cwd, "pyproject.toml"))) {
38
+ return { type: "python", installCommand: "poetry install", testCommand: "pytest" };
39
+ }
40
+ if (fs.existsSync(path.join(cwd, "go.mod"))) {
41
+ return { type: "go", installCommand: "go mod download", testCommand: "go test ./..." };
42
+ }
43
+ return { type: "unknown", installCommand: null, testCommand: null };
44
+ }
45
+
46
+ export interface WorktreePromptOptions {
47
+ branchName: string;
48
+ cwd: string;
49
+ }
50
+
51
+ /**
52
+ * Build the prompt that guides the agent through creating an isolated git worktree.
53
+ * Follows superpowers' using-git-worktrees skill:
54
+ * - Smart directory selection (.worktrees > worktrees > ask)
55
+ * - .gitignore verification
56
+ * - Project setup detection
57
+ * - Baseline test verification
58
+ */
59
+ export function buildWorktreePrompt(options: WorktreePromptOptions): string {
60
+ const { branchName, cwd } = options;
61
+
62
+ return [
63
+ "## Set Up Isolated Worktree",
64
+ "",
65
+ `Create an isolated workspace for branch \`${branchName}\`.`,
66
+ "",
67
+ "### Step 1: Select directory",
68
+ "",
69
+ "Check in priority order:",
70
+ `1. \`${cwd}/.worktrees/\` — if it exists, use it`,
71
+ `2. \`${cwd}/worktrees/\` — if it exists, use it`,
72
+ "3. Check CLAUDE.md for worktree directory preference",
73
+ "4. If none found, ask the user:",
74
+ ' - `.worktrees/` (project-local, hidden)',
75
+ ' - `~/.config/supipowers/worktrees/<project>/` (global location)',
76
+ "",
77
+ "### Step 2: Verify gitignore",
78
+ "",
79
+ "For project-local directories, verify the directory is ignored:",
80
+ "",
81
+ "```bash",
82
+ "git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null",
83
+ "```",
84
+ "",
85
+ "If NOT ignored, add it to .gitignore and commit before proceeding.",
86
+ "",
87
+ "### Step 3: Create worktree",
88
+ "",
89
+ "```bash",
90
+ `git worktree add <dir>/${branchName} -b ${branchName}`,
91
+ `cd <dir>/${branchName}`,
92
+ "```",
93
+ "",
94
+ "### Step 4: Project setup",
95
+ "",
96
+ "Auto-detect and run appropriate setup:",
97
+ "",
98
+ "| File | Command |",
99
+ "|------|---------|",
100
+ "| `package.json` | `npm install` |",
101
+ "| `Cargo.toml` | `cargo build` |",
102
+ "| `requirements.txt` | `pip install -r requirements.txt` |",
103
+ "| `pyproject.toml` | `poetry install` |",
104
+ "| `go.mod` | `go mod download` |",
105
+ "",
106
+ "### Step 5: Verify baseline",
107
+ "",
108
+ "Run the test suite to verify a clean baseline before starting work.",
109
+ "If tests fail, report failures and ask whether to proceed or investigate.",
110
+ "",
111
+ "### Step 6: Report",
112
+ "",
113
+ "```",
114
+ "Worktree ready at <full-path>",
115
+ "Tests passing (<N> tests, 0 failures)",
116
+ `Ready to implement ${branchName}`,
117
+ "```",
118
+ ].join("\n");
119
+ }
package/src/index.ts CHANGED
@@ -5,7 +5,8 @@ import { homedir, tmpdir } from "node:os";
5
5
  import { registerSupiCommand, handleSupi } from "./commands/supi.js";
6
6
  import { registerConfigCommand, handleConfig } from "./commands/config.js";
7
7
  import { registerStatusCommand, handleStatus } from "./commands/status.js";
8
- import { registerPlanCommand } from "./commands/plan.js";
8
+ import { registerPlanCommand, getActiveVisualSessionDir, setActiveVisualSessionDir } from "./commands/plan.js";
9
+ import { getScriptsDir } from "./visual/companion.js";
9
10
  import { registerRunCommand } from "./commands/run.js";
10
11
  import { registerReviewCommand } from "./commands/review.js";
11
12
  import { registerQaCommand } from "./commands/qa.js";
@@ -61,13 +62,21 @@ export default function supipowers(pi: ExtensionAPI): void {
61
62
 
62
63
  // Session start
63
64
  pi.on("session_start", async (_event, ctx) => {
65
+ // Clean up any leftover visual companion from a previous session
66
+ const previousVisualDir = getActiveVisualSessionDir();
67
+ if (previousVisualDir) {
68
+ const stopScript = join(getScriptsDir(), "stop-server.sh");
69
+ pi.exec("bash", [stopScript, previousVisualDir], { cwd: getScriptsDir() }).catch(() => {});
70
+ setActiveVisualSessionDir(null);
71
+ }
72
+
64
73
  // Check for updates in the background
65
74
  const currentVersion = getInstalledVersion();
66
75
  if (!currentVersion) return;
67
76
 
68
77
  pi.exec("npm", ["view", "supipowers", "version"], { cwd: tmpdir() })
69
78
  .then((result) => {
70
- if (result.exitCode !== 0) return;
79
+ if (result.code !== 0) return;
71
80
  const latest = result.stdout.trim();
72
81
  if (latest && latest !== currentVersion) {
73
82
  ctx.ui.notify(
@@ -10,13 +10,13 @@ export interface LspServerStatus {
10
10
  * Check which LSP servers are installed by looking for their binaries.
11
11
  */
12
12
  export async function checkInstalledServers(
13
- exec: (cmd: string, args: string[]) => Promise<{ stdout: string; exitCode: number }>
13
+ exec: (cmd: string, args: string[]) => Promise<{ stdout: string; code: number }>
14
14
  ): Promise<LspServerStatus[]> {
15
15
  const results: LspServerStatus[] = [];
16
16
  for (const server of LSP_SERVERS) {
17
17
  try {
18
18
  const result = await exec("which", [server.server]);
19
- results.push({ server, installed: result.exitCode === 0 });
19
+ results.push({ server, installed: result.code === 0 });
20
20
  } catch {
21
21
  results.push({ server, installed: false });
22
22
  }