@webpresso/plugin-claude 0.0.10 → 0.0.11

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": "0.0.10"
9
+ "version": "0.0.11"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -15,7 +15,14 @@
15
15
  "description": "Webpresso agent-kit: blueprints, skills, lore commit protocol, tech-debt lifecycle",
16
16
  "category": "development",
17
17
  "keywords": ["agent", "blueprint", "claude-code", "skills", "mcp"]
18
+ },
19
+ {
20
+ "name": "typescript-lsp",
21
+ "source": "./plugins/typescript-lsp",
22
+ "description": "TypeScript 7 native language server (tsc --lsp) for Claude Code code intelligence",
23
+ "category": "development",
24
+ "keywords": ["typescript", "lsp", "claude-code", "language-server"]
18
25
  }
19
26
  ],
20
- "version": "0.0.10"
27
+ "version": "0.0.11"
21
28
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-kit",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
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,60 +1,54 @@
1
- #!/usr/bin/env node
2
-
3
- import { spawnSync } from "node:child_process";
4
- import { accessSync, constants, statSync } from "node:fs";
5
- import { dirname, join } from "node:path";
6
- import { homedir } from "node:os";
7
- import { fileURLToPath } from "node:url";
8
-
9
- const shimPath = fileURLToPath(import.meta.url);
10
-
11
- function isExecutableFile(candidate) {
12
- try {
13
- const stat = statSync(candidate);
14
- if (!stat.isFile()) return false;
15
- if (process.platform !== "win32") accessSync(candidate, constants.X_OK);
16
- return true;
17
- } catch {
18
- return false;
19
- }
1
+ #!/bin/sh
2
+ # Resolve the Webpresso `wp` executable and hand this process over to it.
3
+ #
4
+ # `exec` rather than a spawn wrapper: the MCP server this shim launches is a
5
+ # long-lived stdio service, and a wrapper process that merely relays for it is a
6
+ # layer that can die while leaving the server behind, orphaned and holding the
7
+ # client's pipe. After `exec` there is no shim process left to strand — the
8
+ # launcher IS this pid, so the host's signals and pipe closure reach it directly.
9
+ # It also makes every non-MCP command a byte-exact passthrough, including TTY
10
+ # behavior that a relay would otherwise disturb.
11
+ #
12
+ # Arguments are forwarded verbatim through the quoted "$@" expansion. The plugin
13
+ # manifest invokes this file as `bin/wp mcp`, so dropping or word-splitting
14
+ # arguments would silently break the only real launch surface.
15
+
16
+ set -u
17
+
18
+ fail() {
19
+ printf '%s\n' "$1" >&2
20
+ exit 1
20
21
  }
21
22
 
22
- function assertExecutableWp(candidate, label) {
23
- if (isExecutableFile(candidate) && candidate !== shimPath) return candidate;
24
- throw new Error(
25
- `${label} points to ${candidate}, but that executable is not available. ` +
26
- "Set WEBPRESSO_WP_BIN to the Webpresso wp executable, set WP_FORCE_JIT_PATH to an agent-kit checkout, or install the Webpresso app.",
27
- );
28
- }
29
-
30
- function fixedAppWpLauncher() {
31
- const home = process.platform === "win32" ? process.env.USERPROFILE || homedir() : homedir();
32
- return process.platform === "win32"
33
- ? join(home, ".webpresso", "bin", "wp.exe")
34
- : join(home, ".webpresso", "bin", "wp");
35
- }
36
-
37
- function resolveWebpressoWp() {
38
- const explicitPath = process.env.WEBPRESSO_WP_BIN;
39
- const jitRoot = process.env.WP_FORCE_JIT_PATH;
40
- if (explicitPath && jitRoot) {
41
- throw new Error("WEBPRESSO_WP_BIN and WP_FORCE_JIT_PATH are both set; unset one.");
42
- }
43
- if (explicitPath) return assertExecutableWp(explicitPath, "WEBPRESSO_WP_BIN");
44
- if (jitRoot) return assertExecutableWp(join(jitRoot, "bin", "wp"), "WP_FORCE_JIT_PATH");
45
- return assertExecutableWp(fixedAppWpLauncher(), "Webpresso app launcher");
46
- }
47
-
48
- const result = spawnSync(resolveWebpressoWp(), process.argv.slice(2), {
49
- stdio: "inherit",
50
- env: {
51
- ...process.env,
52
- WP_SKIP_UPDATE_CHECK: process.env.WP_SKIP_UPDATE_CHECK ?? "1",
53
- },
54
- });
55
-
56
- if (result.error) {
57
- throw result.error;
58
- }
59
-
60
- process.exit(result.status ?? (result.signal ? 1 : 0));
23
+ : "${WEBPRESSO_WP_BIN:=}"
24
+ : "${WP_FORCE_JIT_PATH:=}"
25
+
26
+ if [ -n "$WEBPRESSO_WP_BIN" ] && [ -n "$WP_FORCE_JIT_PATH" ]; then
27
+ fail "WEBPRESSO_WP_BIN and WP_FORCE_JIT_PATH are both set; unset one. Product path is the Webpresso app launcher (~/.webpresso/bin/wp) or monorepo JIT (WP_FORCE_JIT_PATH to a webpresso/app checkout). Do not dual-set overrides."
28
+ fi
29
+
30
+ if [ -n "$WEBPRESSO_WP_BIN" ]; then
31
+ target=$WEBPRESSO_WP_BIN
32
+ source_label=WEBPRESSO_WP_BIN
33
+ elif [ -n "$WP_FORCE_JIT_PATH" ]; then
34
+ target=$WP_FORCE_JIT_PATH/bin/wp
35
+ source_label=WP_FORCE_JIT_PATH
36
+ else
37
+ target=${HOME:-}/.webpresso/bin/wp
38
+ source_label="Webpresso app launcher"
39
+ fi
40
+
41
+ # Refuse to exec this shim again: a self-referential target would loop forever
42
+ # instead of failing with a diagnostic.
43
+ if [ "$target" = "$0" ]; then
44
+ fail "$source_label points to this shim ($target); set it to the Webpresso wp executable instead."
45
+ fi
46
+
47
+ if [ ! -f "$target" ] || [ ! -x "$target" ]; then
48
+ fail "$source_label points to $target, but that executable is not available. Set WEBPRESSO_WP_BIN to the Webpresso wp executable, set WP_FORCE_JIT_PATH to an agent-kit checkout, or install the Webpresso app."
49
+ fi
50
+
51
+ WP_SKIP_UPDATE_CHECK=${WP_SKIP_UPDATE_CHECK:-1}
52
+ export WP_SKIP_UPDATE_CHECK
53
+
54
+ exec "$target" "$@"
@@ -0,0 +1,102 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook sessionstart-routing <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then true; fi; else true; fi # wp-sessionstart-routing",
9
+ "timeout": 5
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "PreToolUse": [
15
+ {
16
+ "matcher": "Grep|Write|Edit|MultiEdit|Workflow|mcp__.*wp_session_(?:batch_)?execute$",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook pretool-guard <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then printf '%s\\n' \"{\\\"decision\\\":\\\"deny\\\",\\\"reason\\\":\\\"GUARD_PRETOOL_FAILURE: pretool-guard exit $hook_status; run wp hooks doctor\\\",\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PreToolUse\\\",\\\"permissionDecision\\\":\\\"deny\\\",\\\"permissionDecisionReason\\\":\\\"GUARD_PRETOOL_FAILURE: pretool-guard exit $hook_status; run wp hooks doctor\\\"}}\"; printf '%s\\n' \"GUARD_PRETOOL_FAILURE: pretool-guard exit $hook_status; run wp hooks doctor\" >&2; exit 2; fi; else printf '%s\\n' '{\"decision\":\"deny\",\"reason\":\"GUARD_PRETOOL_FAILURE: wp missing; set WEBPRESSO_WP_BIN or install the app\",\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"GUARD_PRETOOL_FAILURE: wp missing; set WEBPRESSO_WP_BIN or install the app\"}}'; printf '%s\\n' 'GUARD_PRETOOL_FAILURE: wp missing; set WEBPRESSO_WP_BIN or install the app' >&2; exit 2; fi # wp-pretool-guard",
21
+ "timeout": 5
22
+ }
23
+ ]
24
+ },
25
+ {
26
+ "matcher": "Bash",
27
+ "hooks": [
28
+ {
29
+ "type": "command",
30
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook pretool-guard <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then printf '%s\\n' \"{\\\"decision\\\":\\\"deny\\\",\\\"reason\\\":\\\"GUARD_PRETOOL_FAILURE: pretool-guard exit $hook_status; run wp hooks doctor\\\",\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PreToolUse\\\",\\\"permissionDecision\\\":\\\"deny\\\",\\\"permissionDecisionReason\\\":\\\"GUARD_PRETOOL_FAILURE: pretool-guard exit $hook_status; run wp hooks doctor\\\"}}\"; printf '%s\\n' \"GUARD_PRETOOL_FAILURE: pretool-guard exit $hook_status; run wp hooks doctor\" >&2; exit 2; fi; else printf '%s\\n' '{\"decision\":\"deny\",\"reason\":\"GUARD_PRETOOL_FAILURE: wp missing; set WEBPRESSO_WP_BIN or install the app\",\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"GUARD_PRETOOL_FAILURE: wp missing; set WEBPRESSO_WP_BIN or install the app\"}}'; printf '%s\\n' 'GUARD_PRETOOL_FAILURE: wp missing; set WEBPRESSO_WP_BIN or install the app' >&2; exit 2; fi # wp-pretool-guard",
31
+ "timeout": 5
32
+ }
33
+ ]
34
+ }
35
+ ],
36
+ "PostToolUse": [
37
+ {
38
+ "matcher": "Write|Edit|MultiEdit",
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook post-tool <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then true; fi; else true; fi # wp-post-tool",
43
+ "timeout": 15
44
+ }
45
+ ]
46
+ }
47
+ ],
48
+ "UserPromptSubmit": [
49
+ {
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook guard-switch <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then true; fi; else true; fi # wp-guard-switch",
54
+ "timeout": 5
55
+ }
56
+ ]
57
+ }
58
+ ],
59
+ "Stop": [
60
+ {
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook stop-qa <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then printf '%s\\n' '{}'; fi; else printf '%s\\n' '{}'; fi # wp-stop-qa",
65
+ "timeout": 10
66
+ }
67
+ ]
68
+ },
69
+ {
70
+ "hooks": [
71
+ {
72
+ "type": "command",
73
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook stop-ultragoal <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then printf '%s\\n' '{}'; fi; else printf '%s\\n' '{}'; fi # wp-stop-ultragoal",
74
+ "timeout": 10
75
+ }
76
+ ]
77
+ }
78
+ ],
79
+ "PreCompact": [
80
+ {
81
+ "hooks": [
82
+ {
83
+ "type": "command",
84
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook precompact-snapshot <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then printf '%s\\n' '{}'; fi; else printf '%s\\n' '{}'; fi # wp-precompact-snapshot",
85
+ "timeout": 5
86
+ }
87
+ ]
88
+ }
89
+ ],
90
+ "PermissionRequest": [
91
+ {
92
+ "hooks": [
93
+ {
94
+ "type": "command",
95
+ "command": "if [ -n \"${CLAUDE_PLUGIN_ROOT}\" ] && [ -x \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" ]; then hook_pid=''; exec 3<&0; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -INT \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -INT \"$$\"' INT; trap 'trap - INT TERM; if [ -n \"$hook_pid\" ]; then kill -TERM \"$hook_pid\" 2>/dev/null || true; wait \"$hook_pid\" 2>/dev/null || true; fi; kill -TERM \"$$\"' TERM; env WP_HOOK_HOST='claude' \"${CLAUDE_PLUGIN_ROOT}/bin/wp\" hook permission-request <&3 & hook_pid=$!; wait \"$hook_pid\"; hook_status=$?; trap - INT TERM; exec 3<&-; if [ \"$hook_status\" -eq 2 ]; then exit 2; elif [ \"$hook_status\" -ne 0 ]; then true; fi; else true; fi # wp-permission-request",
96
+ "timeout": 5
97
+ }
98
+ ]
99
+ }
100
+ ]
101
+ }
102
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpresso/plugin-claude",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
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/app#readme",
@@ -22,6 +22,8 @@
22
22
  "commands/**/*.md",
23
23
  "!commands/**/README.md",
24
24
  "!commands/**/CHANGELOG.md",
25
+ "hooks",
26
+ "plugins",
25
27
  "bin/wp",
26
28
  "LICENSE",
27
29
  "!README.md",
@@ -2,14 +2,14 @@
2
2
  "schemaVersion": 1,
3
3
  "host": "claude",
4
4
  "packageName": "@webpresso/plugin-claude",
5
- "packageVersion": "0.0.10",
5
+ "packageVersion": "0.0.11",
6
6
  "runtimeDirs": [".claude/skills"],
7
7
  "skills": {
8
8
  "ai-deslop": {
9
9
  "digest": "sha256:cf07df5835037f10401400e220c1c923f5325a6149d59c231ce316e10595fdfc"
10
10
  },
11
11
  "autopilot": {
12
- "digest": "sha256:aeace230b2443b5e531179fa5bb5a7a9214d341c72199d8ada0211999627cbb8"
12
+ "digest": "sha256:fc0f77917bd7af3d6e99ce3a96067394308a3b8c94c416b5076167b19e00a754"
13
13
  },
14
14
  "autoresearch": {
15
15
  "digest": "sha256:b4d51cd53beb4a3271827172dfbd0b1d27bd58761ca07a35d49a5d6324b87fdf"
@@ -21,10 +21,10 @@
21
21
  "digest": "sha256:21fd24862e7f7c8a1feadea6bc376492b136b99fc381cf1b8927c9db80615431"
22
22
  },
23
23
  "claude": {
24
- "digest": "sha256:908367f139d3c3e033248be5e4b003475b01b62d4851ad1ff271079af76a53f8"
24
+ "digest": "sha256:e1e97e5419249fbb0cb8446e96fc8e80c165c149db563784570f96ad629ab54d"
25
25
  },
26
26
  "codex": {
27
- "digest": "sha256:9cf714ed78dafbb2370e8f6e4bee5f22db7d540444c4dd96540c8b8dd22bd4a4"
27
+ "digest": "sha256:1f93db92066e5b39ba334ec1d8c3af3de79dea13947dba97b8b7340302906d63"
28
28
  },
29
29
  "deep-interview": {
30
30
  "digest": "sha256:79fbf86a86024a311583a1500bb6960c82ad1383cc9f8ed3f04bbace41848ff7"
@@ -45,13 +45,13 @@
45
45
  "digest": "sha256:38ddebb82a73e9e18e5b9909585a8477285387ac7bbad2574e3708362c4d0475"
46
46
  },
47
47
  "grok": {
48
- "digest": "sha256:796104b04f70c8dd48cf1056c8d72d9492648f89486a35515e00af1d0de42f0a"
48
+ "digest": "sha256:1a6bf596fde9ce50a06ea767c06e65d4845c52d5af085644c958964385363b1e"
49
49
  },
50
50
  "handoff": {
51
51
  "digest": "sha256:eb34b39fc6d416fe8203eea979b4b99ab3150c44da6dad3ca4afb8fe8fb75b85"
52
52
  },
53
53
  "hooks-doctor": {
54
- "digest": "sha256:273bdb0ce597604301648c8c149f20bb92bfa64c9015f4a89e88e932c6501a9e"
54
+ "digest": "sha256:30286e9ef1c64f2c01d05b0e13a39c54741c7a3e02e5d18636795a7517c0b566"
55
55
  },
56
56
  "investigate": {
57
57
  "digest": "sha256:778b3a1f38323e8dd6101c6ace26ff8aada1246b20952b3641d5d1049bc50055"
@@ -60,7 +60,7 @@
60
60
  "digest": "sha256:a80fbacc765e8b886437b9fdf7dd71e1ceb1b98b939078ec90fc88d06a8b4c69"
61
61
  },
62
62
  "opencode-go": {
63
- "digest": "sha256:c9d9e2c59a4e0c895ddd92c5bc5a55d9feb670a9d44cedb96a893eb2aa9cfd7b"
63
+ "digest": "sha256:c47cbe07f96510112d1bccae0a6319d3f74a5e2f3827a59865d45aea757c6dc6"
64
64
  },
65
65
  "plan-ceo-review": {
66
66
  "digest": "sha256:4d426158518dd71f8998770e8d4037bcbfa3c65d7265a93a4a78a9b015ba881e"
@@ -75,31 +75,31 @@
75
75
  "digest": "sha256:b728dad90254d4c9f81b3818321d34ab53519b79ce20ff3bfe08bfacb2aa3e86"
76
76
  },
77
77
  "plan-refine": {
78
- "digest": "sha256:ff848de26414f9b0d015c75051d872db7d2c4de1893a9d5cd55b640392e3f836"
78
+ "digest": "sha256:cf2c0743a81b0d8954417482e7812212a6a90e5046926c44cd82a6a309dfdc26"
79
79
  },
80
80
  "ralplan": {
81
- "digest": "sha256:36d54cf48f92f16cf23362b6616646f883651f0cf8d8ce1b98a386f0021bfe22"
81
+ "digest": "sha256:47cf47910b50471eb92f9487a018311442c95b26907c5b21c3f5b87947bf7e7e"
82
82
  },
83
83
  "team": {
84
84
  "digest": "sha256:c27107b46e0cd7b9c264a6f51f74f505920d63e7ee2a2d26d2f288592fd10bd2"
85
85
  },
86
86
  "tech-debt": {
87
- "digest": "sha256:a34fa1039d68adc4c875af75cb79ddedcee3414a98b63194a9d8eca4671b5264"
87
+ "digest": "sha256:bec6c83a18e55d148af973dd84d34a8750d8a8fe4345e5fca7b9e8c3e876fd9a"
88
88
  },
89
89
  "testing-philosophy": {
90
- "digest": "sha256:22533e26549b60494f042b5f4d7c97abf2019fc0a60697f84a395fa48ef0147f"
90
+ "digest": "sha256:23fdad944b089de3cfcd13957a5ac10c37bd3d136b192029af69368bca1470db"
91
91
  },
92
92
  "tooling-friction": {
93
- "digest": "sha256:12a24fc747e3481aa857ace38993cd0324686ba70ffec115ff1a1955bd5999bc"
93
+ "digest": "sha256:569904882036df09b52864411332ad5ea53e2914bc58d90030a0676f50bee228"
94
94
  },
95
95
  "tph": {
96
96
  "digest": "sha256:bed3684a850651534f315d355cdeae50d951c429817df0f105cccdb7f4e1561b"
97
97
  },
98
98
  "ultragoal": {
99
- "digest": "sha256:137a063d5e286934b92b1d87397b7183f8ea6c564cddc3bb7e6cde5f3f306aaf"
99
+ "digest": "sha256:caa61789eb5ce01940cfaccf7e70e9290c1f318cb31e25d038eb45b26970c39c"
100
100
  },
101
101
  "verify": {
102
- "digest": "sha256:071c47c39e0881e381468cadbbd266f99d29c31eae2caf15c22d57591a1dbf94"
102
+ "digest": "sha256:03bd3b922a24d19ccc0b942d4f56d97f09e24939220a69d8fad8ba1144085d12"
103
103
  }
104
104
  }
105
105
  }
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "typescript-lsp",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript 7 native language server (tsc --lsp) for Claude Code code intelligence",
5
+ "author": {
6
+ "name": "Webpresso",
7
+ "url": "https://github.com/webpresso"
8
+ },
9
+ "lspServers": {
10
+ "typescript": {
11
+ "command": "node",
12
+ "args": ["${CLAUDE_PROJECT_DIR}/node_modules/typescript/lib/tsc.js", "--lsp", "--stdio"],
13
+ "extensionToLanguage": {
14
+ ".ts": "typescript",
15
+ ".tsx": "typescriptreact",
16
+ ".js": "javascript",
17
+ ".jsx": "javascriptreact",
18
+ ".mts": "typescript",
19
+ ".cts": "typescript",
20
+ ".mjs": "javascript",
21
+ ".cjs": "javascript"
22
+ }
23
+ }
24
+ }
25
+ }
@@ -25,7 +25,7 @@ using `wp_ultragoal_run` / `wp ultragoal run` and the current handoff.
25
25
 
26
26
  ## Outside-voice (required)
27
27
 
28
- After each ultragoal **phase or plan-gate milestone**, run an **OpenCode Go** outside-voice review and pick the model by purpose. The purpose→family ordering lives in one place — the committed reviewer policy rendered into the `opencode-go` skill — so follow that skill and do not restate the ordering here. Resolve IDs from live `opencode models opencode-go`. `wp_review_gate` is only for exact-version draft plan approval/auto-promotion; `wp_review_run` is advisory for implementation/phase review and never mutates blueprint approval state. Never self-approve. Full protocol: the `ultragoal` skill. Respect `review_budget` (default owned by `workflow-skills-routing.md`): one sequential path, no multi-host stampede.
28
+ After each ultragoal **phase or plan-gate milestone**, run an **OpenCode Go** outside-voice review and pick the model by purpose. The purpose→family ordering lives in one place — the committed reviewer policy rendered into the `opencode-go` skill — so follow that skill and do not restate the ordering here. Resolve IDs from live `opencode models opencode-go`. `wp_review_gate` in the default authoritative mode is only for exact-version draft plan approval/auto-promotion; the same tool called with `mode: "advisory"` is for implementation/phase review and never mutates blueprint approval state on its own — a later authoritative call may promote a matching advisory approval without re-invoking a provider. Never self-approve. Full protocol: the `ultragoal` skill. Respect `review_budget` (default owned by `workflow-skills-routing.md`): one sequential path, no multi-host stampede.
29
29
 
30
30
  ## Vague gate
31
31
 
@@ -1,186 +1,44 @@
1
1
  ---
2
2
  name: claude
3
- description: "Claude CLI outside-voice wrapper for review, adversarial challenge, or consultation from non-Claude hosts."
3
+ description: "Claude outside-voice reviewer through Webpresso MCP."
4
4
  license: MIT
5
5
  ---
6
6
 
7
- # Claude outside voice
7
+ # Claude outside-voice review
8
8
 
9
- Use when a non-Claude host needs Claude to review a diff, challenge a plan, or answer a focused repo question. Keep it bounded/read-only unless asked otherwise, and report Claude output as advice, not verified fact.
9
+ Use only for a requested content-bound plan or delivery review. Treat output as external advice
10
+ until independently verified.
10
11
 
11
- ## Single-shot budget (anti-stampede)
12
+ ## MCP-only contract
12
13
 
13
- - Default: **one** review invocation per request.
14
- - Do **not** spawn parallel Claude + Codex + Grok + OpenCode reviews unless the user set `review_budget`/`N` > 1.
15
- - Prefer MCP `wp_review_run`, then the `wp review run` CLI fallback, over hand-rolled multi-agent loops.
16
- - Bounded payload only (see below). Split large diffs across sequential calls, never unbounded whole-PR dumps.
14
+ - Call `wp_review_gate` exactly once for the real plan version or delivery diff.
15
+ - Observe the same durable operation with `wp_review_gate_wait` when needed.
16
+ - Never invoke a provider command, the legacy review CLI, or a removed review-run surface.
17
+ - If the review MCP is unavailable, stop and report it unavailable. There is no CLI fallback.
17
18
 
18
- ## Primary path: the `wp_review_run` MCP tool
19
-
20
- When the webpresso MCP server is available, call `wp_review_run` exactly once
21
- instead of any bash block below. It is the same `wp review run` typed runtime,
22
- called in-process, and takes a `prompt` string without `--prompt-file` bookkeeping.
23
- Use the default review stage.
19
+ ## Advisory call
24
20
 
25
21
  ```jsonc
26
- // wp_review_run MCP tool call
27
22
  {
28
- "prompt": "<diff summary + what to look for>",
23
+ "project_id": "<project>",
24
+ "slug": "<blueprint-slug>",
25
+ "purpose": "delivery",
26
+ "base_ref": "<full-base-sha>",
27
+ "authority_ref": "<full-head-sha>",
29
28
  "provider": "claude",
30
- // model, effort, artifactRoot, idleSeconds, and stage are optional and
31
- // default the same way the `wp review run` CLI does. The default stage is
32
- // review.
29
+ "repository_access": "none",
30
+ "mode": "advisory",
33
31
  }
34
32
  ```
35
33
 
36
- Use the requested provider for this invocation. Do not retry, use provider
37
- fallback, or rotate accounts within the invocation. Never shell into a
38
- provider CLI when MCP is available; that bypasses typed artifact capture under
39
- `.webpresso/reviews`.
40
-
41
- For long-running reviews, prefer the async MCP path: call `wp_review_run` with
42
- `"provider": "claude"` and `"background": true`, then poll `wp_review_wait`
43
- with the returned `runId`. Do not solve MCP transport limits by inflating
44
- synchronous review timeouts.
45
-
46
- The bash blocks in this skill (below) are the **MCP-unavailable fallback only**
47
- — use them when the webpresso MCP server itself is not reachable in the current
48
- host, not as a provider-fallback mechanism.
49
-
50
- ## MCP-unavailable fallback: auth check
51
-
52
- Use local Claude CLI login directly; do not route through Anthropic API-key env vars.
53
-
54
- ```bash
55
- AUTH_STATUS_FILE=$(mktemp -t wp-claude-auth.XXXXXX)
56
- trap 'rm -f "$AUTH_STATUS_FILE"' EXIT
57
- if ! claude auth status --json >"$AUTH_STATUS_FILE" 2>/dev/null; then
58
- if ! claude auth status >"$AUTH_STATUS_FILE" 2>/dev/null; then
59
- echo "CLAUDE_AUTH=missing: run claude auth login with the intended Claude Max account"
60
- exit 1
61
- fi
62
- fi
63
- if grep -E '"(authenticated|loggedIn|success)"[[:space:]]*:[[:space:]]*true' "$AUTH_STATUS_FILE" >/dev/null; then
64
- echo "CLAUDE_AUTH=cli-login"
65
- else
66
- echo "CLAUDE_AUTH=missing: claude auth status did not report a recognized Claude CLI login"
67
- exit 1
68
- fi
69
- ```
70
-
71
- ## MCP-unavailable fallback: portable prompt file
72
-
73
- Use a suffix-free `mktemp -t` pattern so macOS and Linux both work:
74
-
75
- ```bash
76
- PROMPT_FILE=$(mktemp -t wp-claude-review.XXXXXX)
77
- trap 'rm -f "$PROMPT_FILE"' EXIT
78
- ```
79
-
80
- ## Dashboard helper relation
81
-
82
- When this skill runs under `wp dash`, record the outside-voice lifecycle with
83
- `wp dash-helper-start --provider claude --role reviewer` and
84
- `wp dash-helper-complete --provider claude --role reviewer --outcome <completed|failed>`
85
- using the actual terminal outcome and artifact path.
86
- Outside the dashboard, skip helper emission. Claude's managed native subagent
87
- lifecycle is not parent-linked; this unsupported coverage must stay explicit,
88
- and completion must never be inferred from transcript text or timing.
89
-
90
- ## Modes
91
-
92
- ### Review
93
-
94
- Use single-file / single-question first for any non-trivial diff. Do not send a whole PR unless it already fits within the bounded payload below.
95
-
96
- **Model policy:** leave `CLAUDE_REVIEW_MODEL` unset unless the user requested a
97
- specific Claude model (for example `fable` for a lighter advisory pass). When it
98
- is unset, `wp review run` lets the Claude CLI choose its own default by omitting
99
- `--model`. The blueprint promotion/completion approval gate
100
- (`catalog/agent/rules/pre-implementation.md`) validates reviewer identity
101
- (`claude`/`codex`/`grok`/an OpenCode-Go model), not the reviewed model string, so do not
102
- claim the gate rejects a different Claude model.
103
-
104
- #### Bounded prompt payload
105
-
106
- Always include:
107
-
108
- - current branch and base branch
109
- - `git diff --stat`
110
- - changed file list
111
- - one targeted file diff or one narrow snippet/hunk only, capped to a fixed size
112
-
113
- Prefer ~12 KB or ~200 lines per call. Split large reviews instead of raising the cap.
114
-
115
- ```bash
116
- BASE_BRANCH=${BASE_BRANCH:-origin/main}
117
- CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
118
- TARGET_FILE=${TARGET_FILE:?set TARGET_FILE to one changed file}
119
-
120
- {
121
- printf 'Outside review mode: focused diff review\n'
122
- printf 'Base branch: %s\nCurrent branch: %s\n\n' "$BASE_BRANCH" "$CURRENT_BRANCH"
123
- printf 'git diff --stat %s...HEAD\n' "$BASE_BRANCH"
124
- git diff --stat "$BASE_BRANCH"...HEAD
125
- printf '\nChanged files:\n'
126
- git diff --name-only "$BASE_BRANCH"...HEAD
127
- printf '\nTarget file: %s\n' "$TARGET_FILE"
128
- printf 'Bounded target diff (max 12000 bytes):\n'
129
- git diff --unified=3 "$BASE_BRANCH"...HEAD -- "$TARGET_FILE" | \
130
- head -c 12000
131
- printf '\n\nQuestion: Identify the highest-signal correctness, security, data-loss, or maintainability risk in %s. Quote only the smallest relevant excerpt. If context is insufficient, answer INSUFFICIENT_CONTEXT.\n' "$TARGET_FILE"
132
- } >"$PROMPT_FILE"
133
- ```
134
-
135
- #### Progress-aware review runtime
136
-
137
- Run one review through the typed `wp review run` owner. Skills must not embed
138
- subprocess supervision. The runtime consumes Claude's streaming JSON events,
139
- advances its idle clock only on monotonic semantic progress, and has no total
140
- wall-clock cutoff.
141
-
142
- The artifact root contains private runtime diagnostics, not a recorded
143
- transcript or committable approval evidence. Direct `wp review run` output is
144
- advisory. `wp_review_gate` is plan-only exact-version draft approval/auto-promotion;
145
- implementation/phase reviews use advisory `wp_review_run` and never mutate
146
- blueprint approval state. CLI delivery gates are MCP-unavailable compatibility only.
147
-
148
- ```bash
149
- CLAUDE_REVIEW_MODEL=${CLAUDE_REVIEW_MODEL:-}
150
- CLAUDE_MODEL_ARGS=()
151
- if [ -n "$CLAUDE_REVIEW_MODEL" ]; then
152
- CLAUDE_MODEL_ARGS=(--model "$CLAUDE_REVIEW_MODEL")
153
- fi
154
- CLAUDE_REVIEW_EFFORT=${CLAUDE_REVIEW_EFFORT:-medium}
155
- CLAUDE_REVIEW_IDLE_SECONDS=${CLAUDE_REVIEW_IDLE_SECONDS:-180}
156
- CLAUDE_REVIEW_ARTIFACT_ROOT=${CLAUDE_REVIEW_ARTIFACT_ROOT:-"$(pwd)/.webpresso/reviews"}
157
- CLAUDE_REVIEW_CODE=0
158
- wp review run \
159
- --provider claude \
160
- --prompt-file "$PROMPT_FILE" \
161
- "${CLAUDE_MODEL_ARGS[@]}" \
162
- --effort "$CLAUDE_REVIEW_EFFORT" \
163
- --stage review \
164
- --artifact-root "$CLAUDE_REVIEW_ARTIFACT_ROOT" \
165
- --idle-seconds "$CLAUDE_REVIEW_IDLE_SECONDS"
166
- CLAUDE_REVIEW_CODE=$?
167
- ```
168
-
169
- Treat `true-idle`, `protocol-unsupported`, provider failure, abort, spawn failure, or artifact failure as an unavailable advisory result. Never replace them with a static timeout, arbitrary byte-growth heartbeat, or buffered-output fallback.
170
-
171
- #### Invocation policy
172
-
173
- Run one provider review per invocation. Do not retry, fall back to another
174
- provider, or rotate accounts within the invocation. A new invocation requires
175
- an explicit diagnosis and caller decision. Do not fall back to an unbounded
176
- whole-PR prompt.
177
-
178
- Summarize findings with severity, evidence, model, artifact path, and whether you independently verified them.
34
+ Use authoritative mode only when formal plan or delivery approval is requested.
179
35
 
180
- ### Challenge
36
+ ## Model policy
181
37
 
182
- Ask Claude to argue against the current plan: hidden assumptions, failure modes, missing tests, and simpler alternatives.
38
+ When the user names an exact model, pass it in the MCP `model` field. Otherwise omit
39
+ that field and let the MCP owner select the configured provider default.
183
40
 
184
- ### Consult
41
+ ## Review quality
185
42
 
186
- Ask a focused repo question. Include only the necessary file paths and snippets; do not send secrets.
43
+ Follow `catalog/agent/rules/review-methodology-sota.md`; report typed verdict, model,
44
+ artifact, grounded findings, and independently verified conclusions.