@webpresso/claude-plugin 3.1.30 → 3.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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Webpresso agent-kit Claude Code plugin: blueprints, skills, hooks, MCP server",
9
- "version": "3.1.30"
9
+ "version": "3.3.0"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -14,17 +14,8 @@
14
14
  "source": "./",
15
15
  "description": "Webpresso agent-kit: blueprints, skills, lore commit protocol, tech-debt lifecycle",
16
16
  "category": "development",
17
- "keywords": ["agent", "blueprint", "claude-code", "skills", "mcp"],
18
- "mcpServers": {
19
- "webpresso": {
20
- "command": "${CLAUDE_PLUGIN_ROOT}/bin/wp",
21
- "args": ["mcp"],
22
- "env": {
23
- "WP_SKIP_UPDATE_CHECK": "1"
24
- }
25
- }
26
- }
17
+ "keywords": ["agent", "blueprint", "claude-code", "skills", "mcp"]
27
18
  }
28
19
  ],
29
- "version": "3.1.30"
20
+ "version": "3.3.0"
30
21
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-kit",
3
- "version": "3.1.30",
3
+ "version": "3.3.0",
4
4
  "description": "Webpresso agent-kit: blueprints, skills, lore commit protocol, tech-debt lifecycle",
5
5
  "author": {
6
6
  "name": "Webpresso",
package/bin/wp CHANGED
@@ -1,21 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { spawnSync } from "node:child_process";
4
- import { accessSync, constants, realpathSync, statSync } from "node:fs";
4
+ import { accessSync, constants, existsSync, readFileSync, realpathSync, statSync } from "node:fs";
5
5
  import { createRequire } from "node:module";
6
- import { dirname, delimiter, join } from "node:path";
6
+ import { dirname, delimiter, isAbsolute, join, relative, resolve } from "node:path";
7
+ import { homedir } from "node:os";
7
8
  import { fileURLToPath } from "node:url";
8
9
 
9
10
  const require = createRequire(import.meta.url);
10
11
  const shimPath = fileURLToPath(import.meta.url);
11
12
  const shimDir = dirname(shimPath);
12
13
  const adapterRoot = dirname(shimDir);
14
+ const pathWpBinNames = process.platform === "win32" ? ["wp.cmd", "wp"] : ["wp"];
13
15
 
14
16
  function isExecutableFile(candidate) {
15
17
  try {
16
18
  const stat = statSync(candidate);
17
19
  if (!stat.isFile()) return false;
18
- accessSync(candidate, constants.X_OK);
20
+ if (process.platform !== "win32") accessSync(candidate, constants.X_OK);
19
21
  return true;
20
22
  } catch {
21
23
  return false;
@@ -34,7 +36,7 @@ function pathWpCandidates() {
34
36
  return (process.env.PATH ?? "")
35
37
  .split(delimiter)
36
38
  .filter(Boolean)
37
- .map((entry) => join(entry, process.platform === "win32" ? "wp.cmd" : "wp"));
39
+ .flatMap((entry) => pathWpBinNames.map((name) => join(entry, name)));
38
40
  }
39
41
 
40
42
  function resolveAgentKitPackageWp() {
@@ -46,14 +48,94 @@ function resolveAgentKitPackageWp() {
46
48
  }
47
49
  }
48
50
 
51
+ function isPathInsideOrEqual(parent, candidate) {
52
+ const parentRoot = realpathSync(parent);
53
+ const candidateRoot = realpathSync(candidate);
54
+ const rel = relative(resolve(parentRoot), resolve(candidateRoot));
55
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
56
+ }
57
+
58
+ function isAgentKitWp(candidate) {
59
+ if (candidate.toLowerCase().endsWith(".cmd")) return false;
60
+ if (!isExecutableFile(candidate) || sameFile(candidate, shimPath)) return false;
61
+ try {
62
+ const resolved = realpathSync(candidate);
63
+ const packageRoot = dirname(dirname(resolved));
64
+ if (resolved !== join(packageRoot, "bin", "wp")) return false;
65
+ return isTrustedAgentKitPackageRoot(packageRoot);
66
+ } catch {
67
+ return false;
68
+ }
69
+ }
70
+
71
+ function isUsableAgentKitPackageRoot(packageRoot) {
72
+ try {
73
+ const pkg = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
74
+ return pkg.name === "@webpresso/agent-kit" && isExecutableFile(join(packageRoot, "bin", "wp"));
75
+ } catch {
76
+ return false;
77
+ }
78
+ }
79
+
80
+ function packageWpFromAdjacentNpmCmdShim(candidate) {
81
+ if (!candidate.toLowerCase().endsWith(".cmd")) return null;
82
+ const packageRoot = join(dirname(candidate), "node_modules", "@webpresso", "agent-kit");
83
+ return isTrustedAgentKitPackageRoot(packageRoot) ? join(packageRoot, "bin", "wp") : null;
84
+ }
85
+
86
+ function currentAgentKitPackageRoot() {
87
+ let current = dirname(shimPath);
88
+ for (let depth = 0; depth < 12; depth += 1) {
89
+ const packagePath = join(current, "package.json");
90
+ if (existsSync(packagePath)) {
91
+ try {
92
+ const pkg = JSON.parse(readFileSync(packagePath, "utf8"));
93
+ if (pkg.name === "@webpresso/agent-kit") return current;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+ const parent = dirname(current);
99
+ if (parent === current) break;
100
+ current = parent;
101
+ }
102
+ return null;
103
+ }
104
+
105
+ function trustedHomeInstallPackageRoots() {
106
+ const home = process.env.HOME || homedir();
107
+ return [
108
+ join(home, ".claude", "plugins", "cache", "webpresso", "agent-kit"),
109
+ join(home, ".bun", "install", "global", "node_modules", "@webpresso", "agent-kit"),
110
+ ];
111
+ }
112
+
113
+ function isTrustedAgentKitPackageRoot(packageRoot) {
114
+ try {
115
+ if (!isUsableAgentKitPackageRoot(packageRoot)) return false;
116
+ const realPackageRoot = realpathSync(packageRoot);
117
+ const sourceRoot = currentAgentKitPackageRoot();
118
+ if (sourceRoot !== null && realPackageRoot === realpathSync(sourceRoot)) return true;
119
+ return trustedHomeInstallPackageRoots().some(
120
+ (anchor) => existsSync(anchor) && isPathInsideOrEqual(anchor, realPackageRoot),
121
+ );
122
+ } catch {
123
+ return false;
124
+ }
125
+ }
126
+
127
+ function assertAgentKitWp(candidate, label) {
128
+ if (isAgentKitWp(candidate)) return candidate;
129
+ throw new Error(
130
+ `${label} points to ${candidate}, but that executable is not @webpresso/agent-kit. ` +
131
+ "Set WEBPRESSO_WP_BIN to the Webpresso wp executable, install/update @webpresso/agent-kit, or run wp setup.",
132
+ );
133
+ }
134
+
49
135
  function resolveAgentKitWp() {
50
136
  const explicitPath = process.env.WEBPRESSO_WP_BIN;
51
137
  if (explicitPath) {
52
- if (isExecutableFile(explicitPath)) return explicitPath;
53
- throw new Error(
54
- `WEBPRESSO_WP_BIN points to ${explicitPath}, but that file is not executable. ` +
55
- "Set WEBPRESSO_WP_BIN to a valid wp executable, install/update @webpresso/agent-kit, or run wp setup.",
56
- );
138
+ return assertAgentKitWp(explicitPath, "WEBPRESSO_WP_BIN");
57
139
  }
58
140
 
59
141
  const candidates = [
@@ -63,8 +145,10 @@ function resolveAgentKitWp() {
63
145
  ].filter(Boolean);
64
146
 
65
147
  for (const candidate of candidates) {
66
- if (isExecutableFile(candidate) && !sameFile(candidate, shimPath)) {
67
- return candidate;
148
+ const packageWp = packageWpFromAdjacentNpmCmdShim(candidate);
149
+ const command = packageWp ?? candidate;
150
+ if (isAgentKitWp(command)) {
151
+ return command;
68
152
  }
69
153
  }
70
154
 
@@ -12,7 +12,7 @@ Use the focused blueprint MCP tools.
12
12
  - `wp_blueprint_put` — whole-document structured authoring; writes the canonical blueprint markdown from typed input and returns revision metadata
13
13
  - `wp_blueprint_transition` — optimistic-concurrency lifecycle transition; requires `expected_version` and returns updated revision metadata
14
14
  - `wp_blueprint_task_next` — return the next ready task; accepts optional `project_id` when the current cwd is a multi-repo workspace container
15
- - `wp_blueprint_task_advance` — change task status (non-`done`); requires `project_id` and accepts optional `request_id` and `head_at_ingest` for retry-safe mutation
15
+ - `wp_blueprint_task_advance` — change task status (non-`done`); requires `project_id` and `slug` (task ids are not unique across blueprints, so `slug` scopes the mutation to the right one), and accepts optional `request_id` and `head_at_ingest` for retry-safe mutation
16
16
  - `wp_blueprint_task_verify` — mark a task `done` with evidence; accepts optional `request_id` and `head_at_ingest` for retry-safe verification
17
17
  - `wp_blueprint_promote` / `wp_blueprint_finalize` — accept optional `project_id` for nested-workspace disambiguation
18
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpresso/claude-plugin",
3
- "version": "3.1.30",
3
+ "version": "3.3.0",
4
4
  "private": false,
5
5
  "description": "Claude Code plugin adapter for Webpresso agent-kit skills, commands, and MCP runtime.",
6
6
  "homepage": "https://github.com/webpresso/agent-kit#readme",
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "host": "claude",
4
4
  "packageName": "@webpresso/claude-plugin",
5
- "packageVersion": "3.1.30",
5
+ "packageVersion": "3.3.0",
6
6
  "runtimeDirs": [".claude/skills"],
7
7
  "skills": {
8
8
  "ai-deslop": {
@@ -24,7 +24,7 @@
24
24
  "digest": "sha256:a97c243b11a25a893d3149a5545d3d111bc54e72c2e2acea9ce6fad3d333d2f1"
25
25
  },
26
26
  "codex": {
27
- "digest": "sha256:07804f1e139e1e2e76f34f35dd5471895072aea5d8b3f5f412cf1328a8180b4b"
27
+ "digest": "sha256:7093f390749bed751038ad480d68c12380cfa2630e61881c16be46da7f75e238"
28
28
  },
29
29
  "deep-interview": {
30
30
  "digest": "sha256:e80d7e12e486397103108bb473e98e8e8656519770fa20701f8b3e9e66991939"
@@ -90,7 +90,7 @@
90
90
  "digest": "sha256:953ab2625287866e5f27e602a89f1752e054d47522d04e1fdc11880867dc2fde"
91
91
  },
92
92
  "verify": {
93
- "digest": "sha256:60de27bef39fd24041e1b78a276fc7ed2f38bc6d7ac5af88beba7eb6770a0119"
93
+ "digest": "sha256:47c1d75ef5d1d47b94ef48ac91b0fd4bbf6ba1ab32563cfc28518bb75c7798f0"
94
94
  }
95
95
  }
96
96
  }
@@ -8,13 +8,37 @@ license: MIT
8
8
 
9
9
  Use this skill from Claude or another non-Codex host when the user wants Codex to independently review a diff, challenge a plan, or answer a repo question. Keep Codex read-only by default and treat its answer as external advice until independently verified.
10
10
 
11
+ ## Primary path: the `wp_review_run` MCP tool
12
+
13
+ When the webpresso MCP server is available, call `wp_review_run` directly instead of any bash block below — it is the same `wp review run` typed runtime, called in-process, with two ergonomic wins: it takes a `prompt` string (no `--prompt-file` bookkeeping) and it runs the probe stage and the review stage in **one call** by default (the review stage is skipped automatically if the probe fails, so you never waste a full review invocation on a cold/broken provider).
14
+
15
+ ```jsonc
16
+ // wp_review_run MCP tool call
17
+ {
18
+ "prompt": "<diff summary + what to look for>",
19
+ "provider": "codex",
20
+ // model, effort, artifactRoot, idleSeconds are all optional and default
21
+ // the same way the `wp review run` CLI does. Omit `stage` for automatic
22
+ // probe-then-review; pass stage: "probe" or stage: "review" only for
23
+ // manual single-stage control.
24
+ }
25
+ ```
26
+
27
+ **Provider fallback lives in this one call.** If your primary provider (e.g. Codex) is unavailable — out of credits, auth expired — switch the `provider` parameter to another supported value (`claude`, `opencode`, `grok`) in the SAME `wp_review_run` call. Never shell into a different provider's CLI directly; that bypasses artifact capture under `.webpresso/reviews`, availability tracking, and the probe-then-review handshake this tool exists to provide. The pretool guard hook actively blocks shelling straight into a provider CLI's review-launching subcommand and redirects here.
28
+
29
+ The bash blocks in this skill (below) are the **MCP-unavailable fallback only** — use them when the webpresso MCP server itself is not reachable in the current host, not as a provider-fallback mechanism.
30
+
11
31
  ## Single-shot budget (anti-stampede)
12
32
 
13
33
  - Default: **one** review invocation per request.
14
34
  - Do **not** fan out parallel multi-host review matrices unless the user set `review_budget`/`N` > 1.
15
- - Prefer `wp review run` / `wp review gate` over spawn/wait agent loops for review.
35
+ - Prefer `wp_review_run` (MCP) or `wp review run` / `wp review gate` (CLI fallback) over spawn/wait agent loops for review.
16
36
  - Keep prompts bounded; no whole-repo paste.
17
37
 
38
+ ## MCP-unavailable fallback (raw CLI)
39
+
40
+ Everything from here down is the manual `wp review run` CLI path documented for hosts or sessions where the webpresso MCP server is not reachable. Prefer `wp_review_run` above whenever MCP is available.
41
+
18
42
  ## Auth check
19
43
 
20
44
  ```bash
@@ -235,8 +235,10 @@ Reviewer preference (pick **one** path):
235
235
 
236
236
  Approval evidence requirements:
237
237
 
238
- - Blueprint lifecycle: `wp review gate <blueprint-slug> --target HEAD --json` first.
239
- Use `wp review log` / `wp review read` for inspection.
238
+ - Blueprint lifecycle: `wp review gate <blueprint-slug> --purpose delivery --target HEAD --json`
239
+ first. Delivery gates automatically run declared Promotion Gates from the
240
+ Trust Dossier before outside-review provider probes. Use `wp review log` /
241
+ `wp review read` for inspection.
240
242
  - Each reviewer must return clear `APPROVED`/`BLOCKED` with enough evidence.
241
243
  - Record as PR comments when a PR exists (model/tool, verdict, reviewed commit).
242
244
  - Unavailable reviewer → try next preferred; if still short, report gap and