@pharaoh-so/mcp 0.3.14 → 0.3.15

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pharaoh",
3
3
  "version": "0.2.3",
4
- "description": "Codebase knowledge graph with 23 development workflow skills. Query architecture, dependencies, blast radius, and more instead of reading files one at a time.",
4
+ "description": "Codebase knowledge graph with focused development workflow skills. Query architecture, dependencies, blast radius, and more instead of reading files one at a time.",
5
5
  "author": {
6
6
  "name": "Pharaoh",
7
7
  "email": "hello@pharaoh.so",
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Architecture-aware planning with Pharaoh reconnaissance
3
+ ---
4
+
5
+ Invoke the `pharaoh-plan` skill to handle this request. Pass through any arguments: $ARGUMENTS
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Architecture-aware code review with Pharaoh
3
+ ---
4
+
5
+ Invoke the `pharaoh-review` skill to handle this request. Pass through any arguments: $ARGUMENTS
@@ -6,8 +6,12 @@
6
6
  */
7
7
  export declare function detectOpenClaw(home?: string): boolean;
8
8
  /**
9
- * Copy all bundled skill directories to ~/.openclaw/skills/.
10
- * Overwrites existing skill dirs on reinstall (cpSync recursive + force).
9
+ * Install bundled skills to `~/.openclaw/skills/` with the same `pharaoh-`
10
+ * prefix that Claude Code installs use. Keeps naming consistent across both
11
+ * platforms and avoids collision with other OpenClaw skills that may ship
12
+ * bare names like `plan` or `review`.
13
+ *
14
+ * Overwrites existing skill dirs on reinstall.
11
15
  *
12
16
  * @param home - Home directory override (defaults to os.homedir()).
13
17
  * @returns Number of skill directories copied.
@@ -5,7 +5,7 @@
5
5
  * OpenClaw's ~/.openclaw/skills/ directory (fallback). Also merges
6
6
  * the Pharaoh MCP server config into the target platform.
7
7
  */
8
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
8
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
9
9
  import { homedir } from "node:os";
10
10
  import { dirname, join } from "node:path";
11
11
  import { fileURLToPath } from "node:url";
@@ -15,6 +15,22 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
15
15
  const PKG_ROOT = join(__dirname, "..");
16
16
  /** Path to the bundled skills directory. */
17
17
  const BUNDLED_SKILLS_DIR = join(PKG_ROOT, "skills");
18
+ /** Path to the bundled slash commands directory. */
19
+ const BUNDLED_COMMANDS_DIR = join(PKG_ROOT, "commands");
20
+ /**
21
+ * Namespace prefix applied to every installed skill. Prevents collision with
22
+ * other plugins that ship same-named bare skills (e.g. `plan`, `review`).
23
+ *
24
+ * Why not use `pharaoh:<skill>` colon-form instead? Claude Code's skill
25
+ * resolver only auto-namespaces skills from plugins installed via the
26
+ * marketplace path (`~/.claude/plugins/cache/<marketplace>/...`). Plugins
27
+ * installed directly to `~/.claude/plugins/data/` — where `npx
28
+ * @pharaoh-so/mcp --install-skills` installs this package — get their
29
+ * skills registered as BARE names without any `<plugin>:` prefix. Applying
30
+ * the prefix as part of the skill's own `name:` field is the only way to
31
+ * get collision-safe distinctive names on this install path.
32
+ */
33
+ const SKILL_PREFIX = "pharaoh-";
18
34
  // ── Detection ───────────────────────────────────────────────────────
19
35
  /**
20
36
  * Detect whether Claude Code is installed by checking for ~/.claude/.
@@ -37,11 +53,17 @@ export function detectOpenClaw(home = homedir()) {
37
53
  // ── Claude Code installer ───────────────────────────────────────────
38
54
  /**
39
55
  * Install Pharaoh as a Claude Code plugin by copying the full plugin
40
- * structure (`.claude-plugin/`, `skills/`, `.mcp.json`) to a persistent
41
- * directory under `~/.claude/plugins/data/pharaoh/`.
56
+ * structure (`.claude-plugin/`, `skills/`, `.mcp.json`, `commands/`) to a
57
+ * persistent directory under `~/.claude/plugins/data/pharaoh/`, plus user-
58
+ * level slash command templates under `~/.claude/commands/`.
59
+ *
60
+ * Claude Code auto-discovers skills from the `skills/` subdirectory when
61
+ * the plugin manifest (`.claude-plugin/plugin.json`) is present.
42
62
  *
43
- * Claude Code auto-discovers skills from the `skills/` subdirectory
44
- * when the plugin manifest (`.claude-plugin/plugin.json`) is present.
63
+ * Each skill is installed with a `pharaoh-` prefix (see SKILL_PREFIX) to
64
+ * avoid collision with other plugins that may ship same-named bare skills.
65
+ * The source directory keeps its bare name — the prefix is applied
66
+ * mechanically during copy with no drift possible.
45
67
  *
46
68
  * @param home - Home directory override (defaults to os.homedir()).
47
69
  * @returns Number of skill directories installed, or -1 on failure.
@@ -59,33 +81,14 @@ function installClaudeCodePlugin(home = homedir()) {
59
81
  process.stderr.write("Pharaoh: .claude-plugin/ manifest not found in package — cannot install.\n");
60
82
  return -1;
61
83
  }
62
- // Copy skills/ and generate pharaoh-* prefixed aliases
63
- let skillCount = 0;
64
- if (existsSync(BUNDLED_SKILLS_DIR)) {
65
- cpSync(BUNDLED_SKILLS_DIR, join(pluginDir, "skills"), { recursive: true, force: true });
66
- const entries = readdirSync(BUNDLED_SKILLS_DIR, { withFileTypes: true });
67
- const skillDirs = entries.filter((e) => e.isDirectory());
68
- skillCount = skillDirs.length;
69
- // Auto-generate pharaoh-* prefixed copies so both `/plan` and `pharaoh:plan`
70
- // resolve to the same content. Without this, prefixed copies drift and users
71
- // get a stripped skeleton when invoking via the pharaoh: prefix.
72
- for (const dir of skillDirs) {
73
- if (dir.name === "pharaoh" || dir.name.startsWith("pharaoh-"))
74
- continue;
75
- const prefixedName = `pharaoh-${dir.name}`;
76
- const prefixedDir = join(pluginDir, "skills", prefixedName);
77
- const srcSkill = join(pluginDir, "skills", dir.name, "SKILL.md");
78
- if (!existsSync(srcSkill))
79
- continue;
80
- mkdirSync(prefixedDir, { recursive: true });
81
- const content = readFileSync(srcSkill, "utf-8");
82
- // Rewrite the name field in YAML frontmatter only (between --- delimiters).
83
- // Using a whole-file /m regex would match `name:` in body content too.
84
- const rewritten = content.replace(/^(---\n[\s\S]*?)(name:\s*).+(\n[\s\S]*?---)/, `$1$2${prefixedName}$3`);
85
- writeFileSync(join(prefixedDir, "SKILL.md"), rewritten);
86
- skillCount++;
87
- }
88
- }
84
+ // Install skills under the pharaoh- prefix for collision-safe names.
85
+ const skillsDst = join(pluginDir, "skills");
86
+ const skillCount = installPrefixedSkills(BUNDLED_SKILLS_DIR, skillsDst, SKILL_PREFIX);
87
+ // Migrate: delete any bare-name skill dirs left from prior installs
88
+ // that used the dual bare+prefixed layout. Without this, users who
89
+ // upgrade keep both copies and Claude Code's prompt-name dedupe picks
90
+ // the wrong one.
91
+ cleanupBareNameSkills(BUNDLED_SKILLS_DIR, skillsDst);
89
92
  // Copy .mcp.json
90
93
  const mcpSrc = join(PKG_ROOT, ".mcp.json");
91
94
  if (existsSync(mcpSrc)) {
@@ -93,6 +96,111 @@ function installClaudeCodePlugin(home = homedir()) {
93
96
  }
94
97
  return skillCount;
95
98
  }
99
+ /**
100
+ * Copy every skill directory from `srcDir` to `dstDir`, prefixing both the
101
+ * target directory name and the `name:` field in its SKILL.md frontmatter
102
+ * with `prefix`.
103
+ *
104
+ * Exception: a source directory whose name equals the prefix stripped of
105
+ * its trailing dash is copied WITHOUT a double-prefix. Example: with
106
+ * `prefix = "pharaoh-"`, the source dir `pharaoh/` is copied to `pharaoh/`
107
+ * unchanged, not `pharaoh-pharaoh/`. This keeps the flagship skill's name
108
+ * clean.
109
+ *
110
+ * @param srcDir - Source skills directory (bundled with the package).
111
+ * @param dstDir - Destination skills directory (inside the plugin path).
112
+ * @param prefix - Namespace prefix to apply (e.g., `"pharaoh-"`).
113
+ * @returns Number of skill directories installed.
114
+ */
115
+ function installPrefixedSkills(srcDir, dstDir, prefix) {
116
+ if (!existsSync(srcDir))
117
+ return 0;
118
+ mkdirSync(dstDir, { recursive: true });
119
+ // `pharaoh-` → `pharaoh` — the source directory name that's exempt from
120
+ // the prefix to avoid `pharaoh-pharaoh`.
121
+ const exemptName = prefix.replace(/-$/, "");
122
+ const entries = readdirSync(srcDir, { withFileTypes: true });
123
+ let count = 0;
124
+ for (const entry of entries) {
125
+ if (!entry.isDirectory())
126
+ continue;
127
+ const srcSkill = join(srcDir, entry.name);
128
+ const srcSkillMd = join(srcSkill, "SKILL.md");
129
+ if (!existsSync(srcSkillMd))
130
+ continue;
131
+ const dstName = entry.name === exemptName ? entry.name : `${prefix}${entry.name}`;
132
+ const dstSkill = join(dstDir, dstName);
133
+ // Copy the full source tree (SKILL.md + any supporting files).
134
+ cpSync(srcSkill, dstSkill, { recursive: true, force: true });
135
+ // Rewrite the frontmatter `name:` field only if we applied the prefix.
136
+ if (dstName !== entry.name) {
137
+ const dstSkillMd = join(dstSkill, "SKILL.md");
138
+ const content = readFileSync(dstSkillMd, "utf-8");
139
+ const rewritten = content.replace(/^(---\n[\s\S]*?)(name:\s*).+(\n[\s\S]*?---)/, `$1$2${dstName}$3`);
140
+ writeFileSync(dstSkillMd, rewritten);
141
+ }
142
+ count++;
143
+ }
144
+ return count;
145
+ }
146
+ /**
147
+ * Delete bare-name skill directories from prior installs that used the dual
148
+ * bare+prefixed layout. Only removes directories that match the name of a
149
+ * bundled source skill (so we don't accidentally delete user-installed
150
+ * skills from other sources that happen to share the `pharaoh/skills/`
151
+ * install path).
152
+ *
153
+ * @param srcDir - Bundled source skills directory.
154
+ * @param dstDir - Installed skills directory.
155
+ * @returns Number of stale directories removed.
156
+ */
157
+ function cleanupBareNameSkills(srcDir, dstDir) {
158
+ if (!existsSync(srcDir) || !existsSync(dstDir))
159
+ return 0;
160
+ const exemptName = SKILL_PREFIX.replace(/-$/, "");
161
+ const sourceNames = new Set(readdirSync(srcDir, { withFileTypes: true })
162
+ .filter((e) => e.isDirectory() && e.name !== exemptName)
163
+ .map((e) => e.name));
164
+ let removed = 0;
165
+ for (const name of sourceNames) {
166
+ const staleDir = join(dstDir, name);
167
+ if (existsSync(staleDir)) {
168
+ rmSync(staleDir, { recursive: true, force: true });
169
+ removed++;
170
+ }
171
+ }
172
+ return removed;
173
+ }
174
+ /**
175
+ * Copy bundled slash command templates (`.md` files in the package's
176
+ * `commands/` directory) to `~/.claude/commands/`, unconditionally
177
+ * overwriting any existing file with the same name.
178
+ *
179
+ * Overwriting is intentional: the install contract is "slash commands just
180
+ * work out of the box," so the canonical shipped versions take precedence
181
+ * over user customizations. Users who want custom command behavior should
182
+ * use different filenames.
183
+ *
184
+ * @param home - Home directory override (defaults to os.homedir()).
185
+ * @returns Number of commands installed.
186
+ */
187
+ function installClaudeCodeCommands(home) {
188
+ if (!existsSync(BUNDLED_COMMANDS_DIR))
189
+ return 0;
190
+ const commandsDst = join(home, ".claude", "commands");
191
+ mkdirSync(commandsDst, { recursive: true });
192
+ const entries = readdirSync(BUNDLED_COMMANDS_DIR, { withFileTypes: true });
193
+ let count = 0;
194
+ for (const entry of entries) {
195
+ if (!entry.isFile() || !entry.name.endsWith(".md"))
196
+ continue;
197
+ const src = join(BUNDLED_COMMANDS_DIR, entry.name);
198
+ const dst = join(commandsDst, entry.name);
199
+ cpSync(src, dst, { force: true });
200
+ count++;
201
+ }
202
+ return count;
203
+ }
96
204
  /**
97
205
  * Register Pharaoh in Claude Code's installed_plugins.json (v2 format).
98
206
  * Adds a new entry or updates the version/lastUpdated of an existing one.
@@ -152,8 +260,12 @@ function registerClaudeCodePlugin(home = homedir()) {
152
260
  }
153
261
  // ── OpenClaw installer ──────────────────────────────────────────────
154
262
  /**
155
- * Copy all bundled skill directories to ~/.openclaw/skills/.
156
- * Overwrites existing skill dirs on reinstall (cpSync recursive + force).
263
+ * Install bundled skills to `~/.openclaw/skills/` with the same `pharaoh-`
264
+ * prefix that Claude Code installs use. Keeps naming consistent across both
265
+ * platforms and avoids collision with other OpenClaw skills that may ship
266
+ * bare names like `plan` or `review`.
267
+ *
268
+ * Overwrites existing skill dirs on reinstall.
157
269
  *
158
270
  * @param home - Home directory override (defaults to os.homedir()).
159
271
  * @returns Number of skill directories copied.
@@ -163,14 +275,11 @@ export function installSkills(home = homedir()) {
163
275
  if (!existsSync(targetDir)) {
164
276
  mkdirSync(targetDir, { recursive: true });
165
277
  }
166
- const entries = readdirSync(BUNDLED_SKILLS_DIR, { withFileTypes: true });
167
- const skillDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
168
- for (const skillName of skillDirs) {
169
- const src = join(BUNDLED_SKILLS_DIR, skillName);
170
- const dst = join(targetDir, skillName);
171
- cpSync(src, dst, { recursive: true, force: true });
172
- }
173
- return skillDirs.length;
278
+ // Prefix skills for collision safety (same rationale as Claude Code path).
279
+ const count = installPrefixedSkills(BUNDLED_SKILLS_DIR, targetDir, SKILL_PREFIX);
280
+ // Also clean up any bare-name leftovers from prior installs.
281
+ cleanupBareNameSkills(BUNDLED_SKILLS_DIR, targetDir);
282
+ return count;
174
283
  }
175
284
  /**
176
285
  * Read ~/.openclaw/openclaw.json, add the Pharaoh MCP server under `mcpServers`,
@@ -263,6 +372,7 @@ export function runInstallSkills(home = homedir(), options) {
263
372
  const count = installClaudeCodePlugin(home);
264
373
  if (count >= 0) {
265
374
  const regResult = registerClaudeCodePlugin(home);
375
+ const commandCount = installClaudeCodeCommands(home);
266
376
  // Silently ensure Pharaoh tools auto-approve (no user prompt on first use)
267
377
  configureClaudeCodePermissions(home);
268
378
  if (!silent) {
@@ -272,10 +382,14 @@ export function runInstallSkills(home = homedir(), options) {
272
382
  current: "Plugin already registered and up-to-date",
273
383
  error: "Could not update installed_plugins.json",
274
384
  };
385
+ const commandLine = commandCount > 0
386
+ ? ` → Installed ${commandCount} slash command${commandCount === 1 ? "" : "s"} to ~/.claude/commands/`
387
+ : null;
275
388
  process.stderr.write([
276
389
  `Pharaoh: installed ${count} skills as Claude Code plugin`,
277
390
  ` → ~/.claude/plugins/data/pharaoh/`,
278
391
  ` → ${regMessages[regResult]}`,
392
+ ...(commandLine ? [commandLine] : []),
279
393
  "",
280
394
  ...(regResult === "added" ? ["Restart Claude Code to pick up the new skills.", ""] : []),
281
395
  ].join("\n"));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pharaoh-so/mcp",
3
3
  "mcpName": "so.pharaoh/pharaoh",
4
- "version": "0.3.14",
4
+ "version": "0.3.15",
5
5
  "description": "MCP proxy for Pharaoh — maps codebases into queryable knowledge graphs for AI agents. Enables Claude Code in headless environments (VPS, SSH, CI) via device flow auth.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -12,6 +12,7 @@
12
12
  "files": [
13
13
  "dist",
14
14
  "skills",
15
+ "commands",
15
16
  ".claude-plugin",
16
17
  ".mcp.json",
17
18
  "inspect-tools.json",
@@ -56,7 +56,7 @@ Save the validated design to a spec file and commit it. Ask the user to review b
56
56
 
57
57
  ### 7. Transition
58
58
 
59
- Once the spec is approved, move to implementation planning. Use `pharaoh:execute` to carry out the plan.
59
+ Once the spec is approved, move to implementation. Use the `plan` skill to break the work into verified steps, then build.
60
60
 
61
61
  ## Working in Existing Codebases
62
62
 
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: plan
3
3
  prompt-name: plan-with-pharaoh
4
- description: Deep plan review with Pharaoh reconnaissance, wiring verification, and structured issue tracking. Use before implementing any feature, refactor, or significant code change. Enters plan mode (no code changes) and provides structured review with decision points.
5
- version: 0.5.0
4
+ description: Architecture-aware plan review adapted from Garry Tan's framework for AI-assisted development. Pharaoh reconnaissance, mandatory mode selection, structured six-section review with decision points. Drop-in replacement that supersedes the legacy ~/.claude/skills/plan-review skill — every section of the legacy skill is present here, plus graceful fallback when Pharaoh is unavailable, stronger mode-selection enforcement, and an explicit framework reference.
5
+ version: 0.6.0
6
6
  homepage: https://pharaoh.so
7
7
  user-invocable: true
8
8
  metadata: {"emoji": "☥", "tags": ["planning", "architecture", "blast-radius", "pharaoh", "review", "interactive"]}
@@ -10,12 +10,16 @@ metadata: {"emoji": "☥", "tags": ["planning", "architecture", "blast-radius",
10
10
 
11
11
  # Plan Review
12
12
 
13
+ Architecture-aware plan review before implementation. Adapted from [Garry Tan's planning framework](https://www.youtube.com/watch?v=bMknfKXIFA8) for AI-assisted development.
14
+
13
15
  **You are now in plan mode. Do NOT make any code changes. Think, evaluate, and present decisions.**
14
16
 
15
17
  ## Document Review
16
18
 
17
19
  If the user provides a document, PRD, prompt, or artifact alongside this command, that IS the plan to review. Apply all review sections to that document. Do not treat it as background context — it is the subject of evaluation.
18
20
 
21
+ Still run Step 1 (Reconnaissance) even when reviewing a document — always verify the plan against the actual codebase state.
22
+
19
23
  ## Project Overrides
20
24
 
21
25
  If a `.claude/plan-review.md` file exists in this project, read it now and apply those rules on top of this baseline. Project rules take precedence where they conflict.
@@ -32,42 +36,40 @@ If a `.claude/plan-review.md` file exists in this project, read it now and apply
32
36
 
33
37
  ## Step 1: Pharaoh Reconnaissance (Required — do this BEFORE reviewing)
34
38
 
35
- Do NOT review from memory or assumptions. Query the actual codebase first:
39
+ Do NOT review from memory or assumptions. Query the actual codebase first.
40
+
41
+ ### If Pharaoh MCP tools are available:
36
42
 
37
43
  1. `get_codebase_map` — current modules, hot files, dependency graph
38
44
  2. `search_functions` for keywords related to the plan — find existing code to reuse/extend
39
45
  3. `get_module_context` on affected modules — entry points, patterns, conventions
40
46
  4. `query_dependencies` between affected modules — coupling, circular deps
47
+ 5. `get_blast_radius` on the primary target of the change — know what breaks
48
+ 6. `check_reachability` on the primary target — verify it's actually reachable from entry points before worrying about it
41
49
 
42
- Ground every recommendation in what actually exists. If you propose adding something, confirm it doesn't already exist. If you propose changing something, know its blast radius.
43
-
44
- ## Step 1b: Reconnaissance Dashboard
45
-
46
- After running recon, present a visual summary before proceeding. This shows the user what Pharaoh found.
50
+ ### Without Pharaoh (graceful fallback):
47
51
 
48
- **Surface all Pharaoh insight blocks verbatim** they contain pre-formatted bar charts, risk meters, and flow diagrams. Do not summarize or paraphrase them.
52
+ 1. Search the codebase for files and functions related to the plan (grep, glob)
53
+ 2. Read the entry points and module structure of affected areas
54
+ 3. Check existing tests for the modules the plan will touch
55
+ 4. Trace imports manually to estimate blast radius
49
56
 
50
- Then compose a **Recon Summary** table:
51
-
52
- | Signal | Value | Source |
53
- |--------|-------|--------|
54
- | Modules affected | N | get_codebase_map |
55
- | Blast radius | LOW/MED/HIGH + caller count | get_blast_radius |
56
- | Existing functions found | N matches | search_functions |
57
- | Cross-module coupling | deps + circular? | query_dependencies |
57
+ Ground every recommendation in what actually exists. If you propose adding something, confirm it doesn't already exist. If you propose changing something, know its blast radius.
58
58
 
59
- If any signal is surprising (high blast radius, circular deps, existing code that overlaps the plan), call it out before moving to Mode Selection.
59
+ ## Step 2: Mode Selection (MANDATORY ask before proceeding)
60
60
 
61
- ## Step 2: Mode Selection
61
+ **STOP and ask the user which mode before starting the review.** This is a hard gate — do not infer, assume, or skip this question even if the user says "yes", "go ahead", or "yes to all". Present both options and wait for an explicit choice:
62
62
 
63
- Ask the user which mode before starting the review:
63
+ > **BIG CHANGE or SMALL CHANGE?**
64
+ >
65
+ > - **BIG CHANGE**: Full interactive review, all relevant sections, up to 4 top issues per section
66
+ > - **SMALL CHANGE**: One question per section, only sections 2-4
64
67
 
65
- **BIG CHANGE**: Full interactive review, all relevant sections, up to 4 top issues per section.
66
- **SMALL CHANGE**: One question per section, only sections 2-4.
68
+ If the user's response is ambiguous (e.g. "just do it", "yes to all"), ask again: "I need to know BIG or SMALL change?" Do not proceed to Step 3 without an answer.
67
69
 
68
70
  ## Step 3: Review Sections
69
71
 
70
- Adapt depth to change size. Skip sections that don't apply.
72
+ Adapt depth to change size. Skip sections that don't apply. **After each section, pause and ask for feedback before moving on.**
71
73
 
72
74
  ### Section 1 — Architecture (skip for small/single-file changes)
73
75
 
@@ -135,7 +137,7 @@ Number each issue (1, 2, 3...) and letter each option (A, B, C...). Recommended
135
137
 
136
138
  ## Workflow Rules
137
139
 
138
- - After each section, pause and ask for feedback before moving on
140
+ - **After each section, pause and ask for feedback before moving on**
139
141
  - Do not assume priorities on timeline or scale
140
142
  - If you see a better approach to the entire plan, say so BEFORE section-by-section review
141
143
  - Challenge the approach if you see a better one — your job is to find problems I'll regret later
@@ -1,89 +0,0 @@
1
- ---
2
- name: audit-tests
3
- prompt-name: audit-tests
4
- description: "Classify tests by real value: ceremony versus protection. Mutation score over line coverage — tests that can't detect mutations are theater. Identify tests that prove nothing, tests that duplicate coverage, and gaps where real protection is missing. Produce an actionable audit with keep, rewrite, and delete verdicts."
5
- version: 0.2.0
6
- homepage: https://pharaoh.so
7
- user-invocable: true
8
- metadata: {"emoji": "☥", "tags": ["test-audit", "mutation-testing", "test-quality", "coverage", "testing"]}
9
- ---
10
-
11
- # Test Audit
12
-
13
- Classify tests by whether they actually protect against regressions. Line coverage is vanity — mutation score is truth. A test that can't detect a mutation in the code it covers is theater.
14
-
15
- ## When to Use
16
-
17
- - Before refactoring a module — know which tests actually protect you
18
- - After inheriting a codebase — separate real coverage from ceremony
19
- - When test suite is slow — find tests to delete without losing protection
20
- - When coverage numbers are high but bugs still ship
21
-
22
- ## Process
23
-
24
- ### 1. Inventory
25
-
26
- List all test files for the target module or area. For each test file, note:
27
-
28
- - What production code it exercises
29
- - Whether it uses mocks or real implementations
30
- - Approximate assertion count
31
-
32
- If Pharaoh tools are available, call `get_test_coverage` to see which modules have tests and which don't.
33
-
34
- ### 2. Classify Each Test
35
-
36
- | Category | Definition | Action |
37
- |----------|-----------|--------|
38
- | **Guardian** | Tests real behavior with real code. Would catch a regression. | Keep |
39
- | **Ceremony** | Passes regardless of code changes. Tests mocks, not behavior. | Rewrite or delete |
40
- | **Duplicate** | Same behavior tested multiple times across files. | Keep one, delete rest |
41
- | **Snapshot** | Records current output without asserting correctness. | Evaluate — keep if output matters, delete if not |
42
- | **Fragile** | Breaks on irrelevant changes (formatting, ordering, timing). | Rewrite to test behavior, not implementation |
43
-
44
- ### 3. Mutation Check
45
-
46
- For critical tests, mentally (or actually) apply mutations to the code under test:
47
-
48
- - Change `>` to `>=`
49
- - Remove an `if` branch
50
- - Return early
51
- - Swap function arguments
52
- - Delete a line
53
-
54
- **If the test still passes after any of these mutations, it's not testing what you think.**
55
-
56
- ### 4. Gap Analysis
57
-
58
- Identify code that has:
59
- - No tests at all
60
- - Only ceremony tests (effectively no real coverage)
61
- - Tests that mock the thing they're supposed to verify
62
-
63
- Prioritize gaps by risk: code in hot paths, security-sensitive code, and code with high blast radius (use `get_blast_radius` if available) needs real tests first.
64
-
65
- ### 5. Produce Audit Report
66
-
67
- For each test file:
68
-
69
- - **Verdict:** KEEP, REWRITE, or DELETE
70
- - **Reason:** one sentence explaining why
71
- - **Priority:** if REWRITE, how urgent (based on risk of the code it covers)
72
-
73
- ## What Makes a Test Valuable
74
-
75
- | Valuable | Not valuable |
76
- |----------|-------------|
77
- | Tests behavior through public API | Tests private implementation details |
78
- | Uses real dependencies | Mocks the thing under test |
79
- | Has hardcoded expected values | Computes expected values from production code |
80
- | Fails when behavior changes | Passes regardless of code changes |
81
- | Describes WHAT should happen | Describes HOW it's currently implemented |
82
-
83
- ## Key Principles
84
-
85
- - **Mutation score > line coverage** — a test that can't detect mutations is worth zero
86
- - **One real integration test > ten mock-heavy unit tests** — mocks hide bugs
87
- - **Hardcoded expectations** — tests that compute their expected output prove nothing
88
- - **Delete with confidence** — removing a ceremony test loses nothing and speeds up the suite
89
- - **If you can't describe what makes a test fail, it's worthless**
@@ -1,34 +0,0 @@
1
- ---
2
- name: debt
3
- prompt-name: find-tech-debt
4
- description: "Categorized technical debt report using Pharaoh knowledge graph. Four-step pro-tier workflow: dead code detection, duplicate logic discovery, undocumented complex functions via spec gaps, and volatile high-complexity module identification. Categorizes findings as DELETE, CONSOLIDATE, DOCUMENT, STABILIZE, or TEST — each with the specific function or file, effort estimate, and risk of ignoring."
5
- version: 0.2.0
6
- homepage: https://pharaoh.so
7
- user-invocable: true
8
- metadata: {"emoji": "☥", "tags": ["tech-debt", "dead-code", "consolidation", "pharaoh", "documentation", "volatility", "test-coverage"]}
9
- ---
10
-
11
- # Find Tech Debt
12
-
13
- Categorized technical debt report. Uses `find-tech-debt` — a 4-step pro-tier workflow that finds and categorizes every class of debt: dead code, duplicates, undocumented complexity, volatile modules, and untested functions. Requires Pro tools.
14
-
15
- ## When to Use
16
-
17
- Invoke when asked to find technical debt, prioritize a cleanup sprint, or understand where the codebase has degraded. Use it before planning a refactoring effort or when the codebase has accumulated changes without systematic review.
18
-
19
- ## Workflow
20
-
21
- 1. Call `get_unused_code` for the target repository to find dead exports and orphaned functions.
22
- 2. Call `get_consolidation_opportunities` for the target repository to find duplicated logic across modules.
23
- 3. Call `get_vision_gaps` for the target repository to find undocumented complex functions and unimplemented specs.
24
- 4. Call `get_codebase_map` for the target repository with `include_metrics` to find volatile and high-complexity modules.
25
-
26
- ## Output
27
-
28
- Categorized findings with one entry per item:
29
-
30
- - **DELETE:** Dead code safe to remove (unreachable, no callers) — with function/file name, effort (small/medium/large), risk of ignoring
31
- - **CONSOLIDATE:** Duplicated logic that should be unified — with affected modules, effort, risk of ignoring
32
- - **DOCUMENT:** Complex functions lacking specs or documentation — with function name, complexity score, effort, risk of ignoring
33
- - **STABILIZE:** Volatile modules that change too often (likely fragile) — with volatility data, effort, risk of ignoring
34
- - **TEST:** High-complexity functions with no test coverage — with function name, complexity score, effort, risk of ignoring
@@ -1,58 +0,0 @@
1
- ---
2
- name: execute
3
- prompt-name: execute-plan
4
- description: "Execute a written implementation plan with review checkpoints. Load plan, review critically, execute tasks sequentially with verification at each step. Stop and ask when blocked — never guess through ambiguity. Finish with branch completion workflow."
5
- version: 0.2.0
6
- homepage: https://pharaoh.so
7
- user-invocable: true
8
- metadata: {"emoji": "☥", "tags": ["execution", "implementation", "plan", "workflow", "development"]}
9
- ---
10
-
11
- # Execute Plan
12
-
13
- Load a written implementation plan, review it critically, then execute every task with verification at each step.
14
-
15
- ## When to Use
16
-
17
- When you have a written plan (spec, PRD, checklist) and need to implement it systematically. The plan should already exist — use `pharaoh:brainstorm` first if it doesn't.
18
-
19
- ## Process
20
-
21
- ### Step 1: Load and Review
22
-
23
- 1. Read the plan file completely
24
- 2. Review critically — identify questions, concerns, or gaps
25
- 3. If concerns exist: raise them with the user before starting
26
- 4. If no concerns: proceed with execution
27
-
28
- ### Step 2: Execute Tasks
29
-
30
- For each task in the plan:
31
-
32
- 1. Mark as in-progress
33
- 2. Follow each step exactly — plans should have bite-sized steps
34
- 3. Run verifications as specified in the plan
35
- 4. Mark as completed before moving to next task
36
-
37
- ### Step 3: Complete
38
-
39
- After all tasks are verified:
40
- - Use `pharaoh:finish` to handle branch completion (merge, PR, or keep)
41
-
42
- ## When to Stop
43
-
44
- **Stop executing immediately when:**
45
- - Hit a blocker (missing dependency, test failure, unclear instruction)
46
- - Plan has critical gaps preventing the next step
47
- - You don't understand an instruction
48
- - Verification fails repeatedly
49
-
50
- Ask for clarification rather than guessing. Don't force through blockers.
51
-
52
- ## Iron Rules
53
-
54
- - Review the plan critically before starting — don't blindly follow a flawed plan
55
- - Follow plan steps exactly — don't improvise unless blocked
56
- - Don't skip verifications — they exist for a reason
57
- - Never start implementation on main/master without explicit user consent
58
- - When blocked, stop and ask — guessing creates more work than waiting
@@ -1,33 +0,0 @@
1
- ---
2
- name: explore
3
- prompt-name: explore-module
4
- description: "Deep-dive into a single codebase module using Pharaoh knowledge graph. Four-step free-tier workflow: full structure with functions, exports, and complexity scores; blast radius of what depends on it; upstream and downstream dependency mapping; and related function discovery. Produces a module briefing with purpose, key functions, dependencies, risk areas, and external API surface."
5
- version: 0.2.0
6
- homepage: https://pharaoh.so
7
- user-invocable: true
8
- metadata: {"emoji": "☥", "tags": ["module-exploration", "architecture", "pharaoh", "dependencies", "complexity", "api-surface"]}
9
- ---
10
-
11
- # Explore Module
12
-
13
- Deep-dive into a single module. Uses `explore-module` — a 4-step free-tier workflow that surfaces a module's structure, what depends on it, how it connects to the rest of the codebase, and what related utilities exist. Produces a complete module briefing without reading files one at a time.
14
-
15
- ## When to Use
16
-
17
- Invoke when asked to understand what a specific module does, before modifying it, or before writing code that will interact with it. Use it instead of opening files and reading them top to bottom.
18
-
19
- ## Workflow
20
-
21
- 1. Call `get_module_context` for the target module to see its full structure — files, functions, exports, and complexity scores.
22
- 2. Call `get_blast_radius` for the target module to understand what depends on it and what it affects.
23
- 3. Call `query_dependencies` for the target module to map its upstream and downstream connections.
24
- 4. Call `search_functions` with key terms from the module name to discover related utilities and entry points.
25
-
26
- ## Output
27
-
28
- A module briefing containing:
29
- - **Purpose:** what this module does, 1-2 sentences
30
- - **Key functions:** highest complexity or most-connected functions, with brief descriptions
31
- - **Dependencies:** what the module imports and what imports it
32
- - **Risk areas:** high-complexity functions, heavily-depended-on exports
33
- - **Entry points:** functions that serve as external API or are called from outside the module