@pharaoh-so/mcp 0.3.44 → 0.3.46
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/commands/review.md +14 -8
- package/package.json +1 -1
- package/skills/review/SKILL.md +15 -9
package/commands/review.md
CHANGED
|
@@ -26,14 +26,20 @@ Before merging any branch. Before opening any PR. When reviewing changes that to
|
|
|
26
26
|
git log --oneline -1 # latest commit
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
2. Determine the base (where this branch diverged from the branch it merges into):
|
|
29
|
+
2. Determine the base (where this branch diverged from the branch it merges into). The target is the first of these that resolves:
|
|
30
30
|
```bash
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
TARGET=$(gh pr view --json baseRefName --jq '"origin/" + .baseRefName' 2>/dev/null) # the open PR's target branch
|
|
32
|
+
[ -n "$TARGET" ] || TARGET=$(git symbolic-ref -q --short refs/remotes/origin/HEAD) # the default branch, set by git clone
|
|
33
|
+
[ -n "$TARGET" ] || for b in origin/main origin/master main master; do
|
|
34
|
+
git rev-parse -q --verify "$b" >/dev/null && TARGET=$b && break
|
|
35
|
+
done
|
|
36
|
+
BASE=$(git merge-base HEAD "$TARGET") && echo "base: $BASE"
|
|
33
37
|
```
|
|
38
|
+
If no base comes out, stop and ask which branch this merges into. An empty base makes every diff below come out empty, and the review would report no changes. If your shell doesn't keep variables between commands, set `BASE` to the printed commit at the start of each one.
|
|
34
39
|
|
|
35
40
|
3. Collect the full changeset from the base:
|
|
36
41
|
```bash
|
|
42
|
+
: "${BASE:?no base: ask which branch this merges into}" # stops here rather than diff HEAD against itself
|
|
37
43
|
git diff --name-only "$BASE"...HEAD # all changed files
|
|
38
44
|
git diff --stat "$BASE"...HEAD # summary stats
|
|
39
45
|
git log --oneline "$BASE"..HEAD # all commits on this branch
|
|
@@ -68,7 +74,7 @@ Pharaoh's graph maps the default branch, so it shows what the change lands on: c
|
|
|
68
74
|
|
|
69
75
|
### Without Pharaoh (graceful fallback)
|
|
70
76
|
|
|
71
|
-
If Pharaoh isn't connected, or doesn't map this repo, build the same picture by hand:
|
|
77
|
+
If Pharaoh isn't connected, or doesn't map this repo, build the same picture by hand. When Pharaoh is connected but doesn't map the repo, tell the user once that mapping it makes this review architecture-aware, with the install link from `pharaoh_account`, then carry on:
|
|
72
78
|
1. Read the top-level layout and the manifest files (package.json, pyproject.toml, go.mod, Cargo.toml) to find the module boundaries
|
|
73
79
|
2. For each changed exported function or file, search for its callers to estimate the blast radius
|
|
74
80
|
3. Read the entry points the change can reach: routes, CLI commands, jobs, event handlers
|
|
@@ -113,7 +119,7 @@ The Security Reviewer agent runs a systematic audit against two layers: universa
|
|
|
113
119
|
- **Logging & monitoring:** Sensitive data in logs, missing audit trails for privileged operations
|
|
114
120
|
|
|
115
121
|
**Layer 2 — The project's own security rules:**
|
|
116
|
-
Take them from the rules collected in Phase 1
|
|
122
|
+
Take them from the project's rules collected in Phase 1 and check each one against the diff by name. Rules like "every query is scoped to the caller's tenant", "tokens are stored hashed" and "webhooks verify their signature" are what this layer exists for. If the project states none, work out its threat model from the code: who the users and tenants are, where secrets live, which inputs are untrusted.
|
|
117
123
|
|
|
118
124
|
**Detection triggers (dispatch when the change touches any of these):**
|
|
119
125
|
- Authentication, sessions, tokens, permissions, and the middleware that guards routes
|
|
@@ -124,7 +130,7 @@ Take them from the rules collected in Phase 1 (`CLAUDE.md`, `AGENTS.md`, `SECURI
|
|
|
124
130
|
- File paths, uploads, shell commands or URLs built from user input
|
|
125
131
|
- Anything the project's rules call security-sensitive
|
|
126
132
|
|
|
127
|
-
With Pharaoh, find these structurally: `get_module_context` on a touched module lists its endpoints, database tables and environment variables, and `get_blast_radius` shows the endpoints, jobs and database operations a changed function reaches. A change that reaches an endpoint, a table or a secret is security-sensitive.
|
|
133
|
+
Always match on file paths and names (auth, session, token, crypto, middleware, webhook, billing, payment, migration), and classify files that are new on this branch from the diff itself. With Pharaoh, also find these structurally: `get_module_context` on a touched module lists its endpoints, database tables and environment variables, and `get_blast_radius` shows the endpoints, jobs and database operations a changed function reaches. A change that reaches an endpoint, a table or a secret is security-sensitive. Pharaoh's graph is the default branch, so it sees what existing code a change reaches, never the files the branch adds.
|
|
128
134
|
|
|
129
135
|
**Output format:** Each finding must include:
|
|
130
136
|
1. Vulnerability class (e.g., "SQL Injection", "Missing Authorization Check")
|
|
@@ -251,7 +257,7 @@ If none of these triggers are met, **skip Phase 3** and proceed to Phase 4.
|
|
|
251
257
|
### Auto-block triggers (any of these = BLOCK)
|
|
252
258
|
|
|
253
259
|
- Any CRITICAL security finding (injection, broken access control, tenant isolation violation, secret exposure)
|
|
254
|
-
- Unreachable exports (new public code
|
|
260
|
+
- Unreachable exports in an application (new public code that nothing calls). In a library, exports are the public API: check each new one is documented or tested instead. Without graph reachability data, a search can't prove nothing calls it: raise it under SHIP WITH CHANGES, not BLOCK
|
|
255
261
|
- New circular dependencies between modules
|
|
256
262
|
- HIGH regression risk without corresponding test coverage
|
|
257
263
|
- **A MUST-bullet in `docs/VISION.md` is violated by this change** (without VISION.md being updated in the same PR with user approval)
|
|
@@ -270,7 +276,7 @@ If none of these triggers are met, **skip Phase 3** and proceed to Phase 4.
|
|
|
270
276
|
### SHIP triggers
|
|
271
277
|
|
|
272
278
|
- No CRITICAL or confirmed IMPORTANT findings
|
|
273
|
-
- All new exports are reachable
|
|
279
|
+
- All new exports are reachable (applications) or documented or tested (libraries)
|
|
274
280
|
- Regression risk is LOW or MEDIUM with adequate test coverage
|
|
275
281
|
- Spec alignment is clean or intentionally divergent with documentation
|
|
276
282
|
|
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.
|
|
4
|
+
"version": "0.3.46",
|
|
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",
|
package/skills/review/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: review
|
|
3
3
|
prompt-name: review-with-pharaoh
|
|
4
4
|
description: "The definitive code review, for any codebase. Five-phase workflow: git context detection (worktree, branch, base, changed files), Pharaoh recon (architecture map, module context, blast radius in one call, with a fallback when the repo isn't mapped), parallel specialized agent dispatch (code quality, security against the project's own rules, error handling, test coverage, type design), adversarial review for security-sensitive changes, and a final synthesized verdict of SHIP / SHIP WITH CHANGES / BLOCK. Architecture-aware wherever Pharaoh maps the repo, always branch-aware."
|
|
5
|
-
version: 0.4.
|
|
5
|
+
version: 0.4.2
|
|
6
6
|
homepage: https://pharaoh.so
|
|
7
7
|
user-invocable: true
|
|
8
8
|
metadata: {"emoji": "☥", "tags": ["code-review", "pull-request", "architecture", "pharaoh", "multi-agent", "adversarial-review", "regression-risk", "spec-alignment"]}
|
|
@@ -32,14 +32,20 @@ Before merging any branch. Before opening any PR. When reviewing changes that to
|
|
|
32
32
|
git log --oneline -1 # latest commit
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
2. Determine the base (where this branch diverged from the branch it merges into):
|
|
35
|
+
2. Determine the base (where this branch diverged from the branch it merges into). The target is the first of these that resolves:
|
|
36
36
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
TARGET=$(gh pr view --json baseRefName --jq '"origin/" + .baseRefName' 2>/dev/null) # the open PR's target branch
|
|
38
|
+
[ -n "$TARGET" ] || TARGET=$(git symbolic-ref -q --short refs/remotes/origin/HEAD) # the default branch, set by git clone
|
|
39
|
+
[ -n "$TARGET" ] || for b in origin/main origin/master main master; do
|
|
40
|
+
git rev-parse -q --verify "$b" >/dev/null && TARGET=$b && break
|
|
41
|
+
done
|
|
42
|
+
BASE=$(git merge-base HEAD "$TARGET") && echo "base: $BASE"
|
|
39
43
|
```
|
|
44
|
+
If no base comes out, stop and ask which branch this merges into. An empty base makes every diff below come out empty, and the review would report no changes. If your shell doesn't keep variables between commands, set `BASE` to the printed commit at the start of each one.
|
|
40
45
|
|
|
41
46
|
3. Collect the full changeset from the base:
|
|
42
47
|
```bash
|
|
48
|
+
: "${BASE:?no base: ask which branch this merges into}" # stops here rather than diff HEAD against itself
|
|
43
49
|
git diff --name-only "$BASE"...HEAD # all changed files
|
|
44
50
|
git diff --stat "$BASE"...HEAD # summary stats
|
|
45
51
|
git log --oneline "$BASE"..HEAD # all commits on this branch
|
|
@@ -74,7 +80,7 @@ Pharaoh's graph maps the default branch, so it shows what the change lands on: c
|
|
|
74
80
|
|
|
75
81
|
### Without Pharaoh (graceful fallback)
|
|
76
82
|
|
|
77
|
-
If Pharaoh isn't connected, or doesn't map this repo, build the same picture by hand:
|
|
83
|
+
If Pharaoh isn't connected, or doesn't map this repo, build the same picture by hand. When Pharaoh is connected but doesn't map the repo, tell the user once that mapping it makes this review architecture-aware, with the install link from `pharaoh_account`, then carry on:
|
|
78
84
|
1. Read the top-level layout and the manifest files (package.json, pyproject.toml, go.mod, Cargo.toml) to find the module boundaries
|
|
79
85
|
2. For each changed exported function or file, search for its callers to estimate the blast radius
|
|
80
86
|
3. Read the entry points the change can reach: routes, CLI commands, jobs, event handlers
|
|
@@ -119,7 +125,7 @@ The Security Reviewer agent runs a systematic audit against two layers: universa
|
|
|
119
125
|
- **Logging & monitoring:** Sensitive data in logs, missing audit trails for privileged operations
|
|
120
126
|
|
|
121
127
|
**Layer 2 — The project's own security rules:**
|
|
122
|
-
Take them from the rules collected in Phase 1
|
|
128
|
+
Take them from the project's rules collected in Phase 1 and check each one against the diff by name. Rules like "every query is scoped to the caller's tenant", "tokens are stored hashed" and "webhooks verify their signature" are what this layer exists for. If the project states none, work out its threat model from the code: who the users and tenants are, where secrets live, which inputs are untrusted.
|
|
123
129
|
|
|
124
130
|
**Detection triggers (dispatch when the change touches any of these):**
|
|
125
131
|
- Authentication, sessions, tokens, permissions, and the middleware that guards routes
|
|
@@ -130,7 +136,7 @@ Take them from the rules collected in Phase 1 (`CLAUDE.md`, `AGENTS.md`, `SECURI
|
|
|
130
136
|
- File paths, uploads, shell commands or URLs built from user input
|
|
131
137
|
- Anything the project's rules call security-sensitive
|
|
132
138
|
|
|
133
|
-
With Pharaoh, find these structurally: `get_module_context` on a touched module lists its endpoints, database tables and environment variables, and `get_blast_radius` shows the endpoints, jobs and database operations a changed function reaches. A change that reaches an endpoint, a table or a secret is security-sensitive.
|
|
139
|
+
Always match on file paths and names (auth, session, token, crypto, middleware, webhook, billing, payment, migration), and classify files that are new on this branch from the diff itself. With Pharaoh, also find these structurally: `get_module_context` on a touched module lists its endpoints, database tables and environment variables, and `get_blast_radius` shows the endpoints, jobs and database operations a changed function reaches. A change that reaches an endpoint, a table or a secret is security-sensitive. Pharaoh's graph is the default branch, so it sees what existing code a change reaches, never the files the branch adds.
|
|
134
140
|
|
|
135
141
|
**Output format:** Each finding must include:
|
|
136
142
|
1. Vulnerability class (e.g., "SQL Injection", "Missing Authorization Check")
|
|
@@ -257,7 +263,7 @@ If none of these triggers are met, **skip Phase 3** and proceed to Phase 4.
|
|
|
257
263
|
### Auto-block triggers (any of these = BLOCK)
|
|
258
264
|
|
|
259
265
|
- Any CRITICAL security finding (injection, broken access control, tenant isolation violation, secret exposure)
|
|
260
|
-
- Unreachable exports (new public code
|
|
266
|
+
- Unreachable exports in an application (new public code that nothing calls). In a library, exports are the public API: check each new one is documented or tested instead. Without graph reachability data, a search can't prove nothing calls it: raise it under SHIP WITH CHANGES, not BLOCK
|
|
261
267
|
- New circular dependencies between modules
|
|
262
268
|
- HIGH regression risk without corresponding test coverage
|
|
263
269
|
- **A MUST-bullet in `docs/VISION.md` is violated by this change** (without VISION.md being updated in the same PR with user approval)
|
|
@@ -276,7 +282,7 @@ If none of these triggers are met, **skip Phase 3** and proceed to Phase 4.
|
|
|
276
282
|
### SHIP triggers
|
|
277
283
|
|
|
278
284
|
- No CRITICAL or confirmed IMPORTANT findings
|
|
279
|
-
- All new exports are reachable
|
|
285
|
+
- All new exports are reachable (applications) or documented or tested (libraries)
|
|
280
286
|
- Regression risk is LOW or MEDIUM with adequate test coverage
|
|
281
287
|
- Spec alignment is clean or intentionally divergent with documentation
|
|
282
288
|
|