@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.
@@ -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
- DEFAULT=$(git symbolic-ref --short refs/remotes/origin/HEAD) # the default branch, e.g. origin/main
32
- BASE=$(git merge-base HEAD "$DEFAULT") # use the PR's target branch if it isn't the default
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 (`CLAUDE.md`, `AGENTS.md`, `SECURITY.md`, `docs/VISION.md`) 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.
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. Without Pharaoh, match on file paths and names (auth, session, token, crypto, middleware, webhook, billing, payment, migration).
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 with zero callers)
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.44",
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",
@@ -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.0
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
- DEFAULT=$(git symbolic-ref --short refs/remotes/origin/HEAD) # the default branch, e.g. origin/main
38
- BASE=$(git merge-base HEAD "$DEFAULT") # use the PR's target branch if it isn't the default
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 (`CLAUDE.md`, `AGENTS.md`, `SECURITY.md`, `docs/VISION.md`) 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.
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. Without Pharaoh, match on file paths and names (auth, session, token, crypto, middleware, webhook, billing, payment, migration).
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 with zero callers)
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