@boyingliu01/xp-gate 0.26.0 → 0.27.1

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.
Files changed (119) hide show
  1. package/bin/xp-gate.js +161 -28
  2. package/hooks/pre-commit +27 -10
  3. package/lib/__tests__/check-alignment-cli.test.mjs +77 -0
  4. package/lib/__tests__/doctor-469-hook-env.test.js +12 -7
  5. package/lib/__tests__/doctor-exec-retry.test.js +152 -0
  6. package/lib/__tests__/doctor-module-resolution-parity.test.js +15 -6
  7. package/lib/__tests__/doctor-tui-skill-freshness.test.js +16 -4
  8. package/lib/__tests__/test-alignment.test.ts +37 -0
  9. package/lib/__tests__/windows-bash-probe.test.js +123 -0
  10. package/lib/check-alignment-runner.cjs +74 -0
  11. package/lib/detect-deps.js +139 -20
  12. package/lib/doctor.js +45 -11
  13. package/lib/gate-runner.js +12 -5
  14. package/lib/mattpocock-license-verdict.json +1 -1
  15. package/lib/sprint-status.js +5 -2
  16. package/lib/test-alignment.ts +136 -12
  17. package/mock-policy/AGENTS.md +2 -2
  18. package/mutation/AGENTS.md +2 -2
  19. package/package.json +1 -1
  20. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  21. package/plugins/claude-code/skills/delphi-review/AGENTS.md +2 -2
  22. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +2 -2
  23. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +2 -2
  24. package/plugins/dsh/README.md +1 -1
  25. package/plugins/dsh/package.json +1 -1
  26. package/plugins/dsh/scripts/prepack.cjs +2 -2
  27. package/plugins/dsh/skills/delphi-review/AGENTS.md +2 -2
  28. package/plugins/dsh/skills/sprint-flow/AGENTS.md +2 -2
  29. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +2 -2
  30. package/plugins/dsh/src/skills.test.ts +20 -7
  31. package/plugins/opencode/package.json +1 -1
  32. package/plugins/opencode/scripts/prepack.cjs +0 -1
  33. package/plugins/opencode/skills/delphi-review/AGENTS.md +2 -2
  34. package/plugins/opencode/skills/sprint-flow/AGENTS.md +2 -2
  35. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +2 -2
  36. package/plugins/qoder/plugin.json +1 -1
  37. package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
  38. package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
  39. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
  40. package/principles/AGENTS.md +2 -2
  41. package/principles/rules/__tests__/clean-code/code-duplication.test.ts +9 -8
  42. package/principles/rules/__tests__/clean-code/deep-nesting.test.ts +3 -4
  43. package/principles/rules/__tests__/clean-code/god-class.test.ts +2 -4
  44. package/principles/rules/__tests__/clean-code/large-file.test.ts +2 -4
  45. package/principles/rules/__tests__/clean-code/long-function.test.ts +2 -4
  46. package/principles/rules/__tests__/clean-code/many-exports.test.ts +2 -3
  47. package/principles/rules/__tests__/clean-code/missing-error-handling.test.ts +2 -4
  48. package/principles/rules/__tests__/clean-code/too-many-params.test.ts +2 -4
  49. package/principles/rules/__tests__/clean-code/unused-imports.test.ts +4 -4
  50. package/principles/rules/__tests__/solid/dip.test.ts +2 -4
  51. package/principles/rules/__tests__/solid/isp.test.ts +2 -4
  52. package/principles/rules/__tests__/solid/lsp.test.ts +2 -4
  53. package/principles/rules/__tests__/solid/ocp.test.ts +2 -4
  54. package/principles/rules/__tests__/solid/srp.test.ts +2 -4
  55. package/principles/rules/clean-code/code-duplication.ts +12 -14
  56. package/principles/rules/clean-code/deep-nesting.ts +18 -20
  57. package/principles/rules/clean-code/god-class.ts +32 -34
  58. package/principles/rules/clean-code/large-file.ts +14 -16
  59. package/principles/rules/clean-code/long-function.ts +26 -28
  60. package/principles/rules/clean-code/magic-numbers.ts +39 -38
  61. package/principles/rules/clean-code/many-exports.ts +21 -23
  62. package/principles/rules/clean-code/missing-error-handling.ts +13 -15
  63. package/principles/rules/clean-code/too-many-params.ts +15 -17
  64. package/principles/rules/clean-code/unused-imports.ts +13 -15
  65. package/principles/rules/solid/dip.ts +16 -18
  66. package/principles/rules/solid/isp.ts +17 -19
  67. package/principles/rules/solid/lsp.ts +4 -6
  68. package/principles/rules/solid/ocp.ts +17 -19
  69. package/principles/rules/solid/srp.ts +20 -22
  70. package/scripts/__tests__/sync-package-content.test.js +0 -1
  71. package/scripts/sync-package-content.js +0 -1
  72. package/skills/delphi-review/AGENTS.md +2 -2
  73. package/skills/sprint-flow/AGENTS.md +2 -2
  74. package/skills/test-specification-alignment/AGENTS.md +2 -2
  75. package/plugins/claude-code/skills/clipboard-vision/SKILL.md +0 -48
  76. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +0 -64
  77. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +0 -185
  78. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +0 -138
  79. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +0 -273
  80. package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.ps1 +0 -115
  81. package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.sh +0 -161
  82. package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.ps1 +0 -86
  83. package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.sh +0 -137
  84. package/plugins/dsh/skills/clipboard-vision/SKILL.md +0 -48
  85. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +0 -64
  86. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +0 -185
  87. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +0 -138
  88. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +0 -273
  89. package/plugins/dsh/skills/clipboard-vision/describe-clipboard.ps1 +0 -115
  90. package/plugins/dsh/skills/clipboard-vision/describe-clipboard.sh +0 -161
  91. package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.ps1 +0 -86
  92. package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.sh +0 -137
  93. package/plugins/opencode/skills/clipboard-vision/SKILL.md +0 -48
  94. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +0 -64
  95. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +0 -185
  96. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +0 -138
  97. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +0 -273
  98. package/plugins/opencode/skills/clipboard-vision/describe-clipboard.ps1 +0 -115
  99. package/plugins/opencode/skills/clipboard-vision/describe-clipboard.sh +0 -161
  100. package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.ps1 +0 -86
  101. package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.sh +0 -137
  102. package/plugins/qoder/skills/clipboard-vision/SKILL.md +0 -48
  103. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +0 -64
  104. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +0 -185
  105. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +0 -138
  106. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +0 -273
  107. package/plugins/qoder/skills/clipboard-vision/describe-clipboard.ps1 +0 -115
  108. package/plugins/qoder/skills/clipboard-vision/describe-clipboard.sh +0 -161
  109. package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.ps1 +0 -86
  110. package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.sh +0 -137
  111. package/skills/clipboard-vision/SKILL.md +0 -48
  112. package/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +0 -64
  113. package/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +0 -185
  114. package/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +0 -138
  115. package/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +0 -273
  116. package/skills/clipboard-vision/describe-clipboard.ps1 +0 -115
  117. package/skills/clipboard-vision/describe-clipboard.sh +0 -161
  118. package/skills/clipboard-vision/scripts/clipboard-vision.ps1 +0 -86
  119. package/skills/clipboard-vision/scripts/clipboard-vision.sh +0 -137
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- api_base="${CLIPBOARD_VISION_API_BASE:-http://127.0.0.1:11434/v1}"
5
- model="${CLIPBOARD_VISION_MODEL:-}"
6
- api_key="${CLIPBOARD_VISION_API_KEY:-}"
7
- max_bytes="${CLIPBOARD_VISION_MAX_BYTES:-10485760}"
8
- allow_remote=false
9
- confirm_remote=""
10
- while [ "$#" -gt 0 ]; do
11
- case "$1" in
12
- --allow-remote) allow_remote=true; shift ;;
13
- --confirm-remote)
14
- [ "$#" -ge 2 ] || { printf '%s\n' 'Error: --confirm-remote requires the disclosed token' >&2; exit 2; }
15
- confirm_remote="$2"
16
- shift 2
17
- ;;
18
- --help)
19
- printf '%s\n' 'Usage: clipboard-vision.sh [--allow-remote --confirm-remote TOKEN]'
20
- exit 0
21
- ;;
22
- *) printf 'Error: unknown option: %s\n' "$1" >&2; exit 2 ;;
23
- esac
24
- done
25
-
26
- [ -n "$model" ] || { printf '%s\n' 'Error: CLIPBOARD_VISION_MODEL is required' >&2; exit 2; }
27
- case "$max_bytes" in *[!0-9]*|'') printf '%s\n' 'Error: CLIPBOARD_VISION_MAX_BYTES must be a positive integer' >&2; exit 2 ;; esac
28
- [ "$max_bytes" -gt 0 ] || { printf '%s\n' 'Error: CLIPBOARD_VISION_MAX_BYTES must be positive' >&2; exit 2; }
29
-
30
- endpoint_info=$(python3 - "$api_base" "$model" <<'PY'
31
- import hashlib
32
- import ipaddress
33
- import sys
34
- import urllib.parse
35
-
36
- url = urllib.parse.urlparse(sys.argv[1])
37
- if url.scheme not in {"http", "https"} or not url.hostname or url.username or url.password or url.query or url.fragment:
38
- raise SystemExit(2)
39
- try:
40
- loopback = ipaddress.ip_address(url.hostname).is_loopback
41
- except ValueError:
42
- loopback = False
43
- try:
44
- port = url.port or (443 if url.scheme == "https" else 80)
45
- except ValueError:
46
- raise SystemExit(2)
47
- print("local" if loopback else "remote")
48
- hostname = url.hostname.lower()
49
- print(hostname)
50
- display_host = f"[{hostname}]" if ":" in hostname else hostname
51
- base_path = url.path.rstrip("/")
52
- effective = f"{url.scheme.lower()}://{display_host}:{port}{base_path}/chat/completions"
53
- print(effective)
54
- print(hashlib.sha256(f"{effective}\n{sys.argv[2]}".encode()).hexdigest())
55
- PY
56
- ) || { printf '%s\n' 'Error: invalid CLIPBOARD_VISION_API_BASE' >&2; exit 2; }
57
- endpoint_kind=$(printf '%s\n' "$endpoint_info" | sed -n '1p')
58
- effective_endpoint=$(printf '%s\n' "$endpoint_info" | sed -n '3p')
59
- expected_confirmation=$(printf '%s\n' "$endpoint_info" | sed -n '4p')
60
-
61
- if [ "$endpoint_kind" = remote ]; then
62
- printf 'Remote disclosure: clipboard image data will be sent to %s using model %s.\n' "$effective_endpoint" "$model" >&2
63
- printf 'Confirmation token for this canonical endpoint and model: %s\n' "$expected_confirmation" >&2
64
- if [ "$allow_remote" != true ] || [ "$confirm_remote" != "$expected_confirmation" ]; then
65
- printf '%s\n' 'Error: remote endpoint requires --allow-remote and the disclosed --confirm-remote token' >&2
66
- exit 2
67
- fi
68
- fi
69
-
70
- work_dir=$(mktemp -d "${TMPDIR:-/tmp}/clipboard-vision.XXXXXX")
71
- image_file="$work_dir/clipboard.png"
72
- request_file="$work_dir/request.json"
73
- response_file="$work_dir/response.json"
74
- auth_file="$work_dir/auth-header"
75
- cleanup() { rm -rf -- "$work_dir"; }
76
- trap cleanup EXIT HUP INT TERM
77
-
78
- if command -v pngpaste >/dev/null 2>&1; then
79
- pngpaste "$image_file"
80
- elif command -v wl-paste >/dev/null 2>&1; then
81
- wl-paste --no-newline --type image/png > "$image_file"
82
- elif command -v import >/dev/null 2>&1; then
83
- import clipboard: "$image_file"
84
- else
85
- printf '%s\n' 'Error: install pngpaste, wl-paste, or ImageMagick import' >&2
86
- exit 2
87
- fi
88
-
89
- [ -s "$image_file" ] || { printf '%s\n' 'Error: clipboard does not contain an image' >&2; exit 2; }
90
- image_bytes=$(wc -c < "$image_file" | tr -d '[:space:]')
91
- [ "$image_bytes" -le "$max_bytes" ] || { printf 'Error: clipboard image exceeds %s bytes\n' "$max_bytes" >&2; exit 2; }
92
-
93
- python3 - "$image_file" "$request_file" "$model" <<'PY'
94
- import base64
95
- import json
96
- import pathlib
97
- import sys
98
-
99
- image = base64.b64encode(pathlib.Path(sys.argv[1]).read_bytes()).decode("ascii")
100
- request = {
101
- "model": sys.argv[3],
102
- "messages": [{"role": "user", "content": [
103
- {"type": "text", "text": "Describe this clipboard image."},
104
- {"type": "image_url", "image_url": {"url": "data:image/png;base64," + image}},
105
- ]}],
106
- }
107
- pathlib.Path(sys.argv[2]).write_text(json.dumps(request), encoding="utf-8")
108
- PY
109
-
110
- curl_args=(--silent --show-error --max-redirs 0 --output "$response_file" --write-out '%{http_code}' --header 'Content-Type: application/json' --data-binary "@$request_file")
111
- if [ -n "$api_key" ]; then
112
- case "$api_key" in *$'\n'*|*$'\r'*) printf '%s\n' 'Error: invalid CLIPBOARD_VISION_API_KEY' >&2; exit 2 ;; esac
113
- umask 077
114
- printf 'Authorization: Bearer %s\n' "$api_key" > "$auth_file"
115
- chmod 600 "$auth_file"
116
- curl_args+=(--header "@$auth_file")
117
- fi
118
- status=$(curl "${curl_args[@]}" "$effective_endpoint") || { printf '%s\n' 'Error: vision API request failed' >&2; exit 1; }
119
- case "$status" in 2??) ;; *) printf 'Error: vision API returned HTTP %s (body redacted)\n' "$status" >&2; exit 1 ;; esac
120
-
121
- result=$(python3 - "$response_file" <<'PY'
122
- import json
123
- import pathlib
124
- import sys
125
-
126
- try:
127
- data = json.loads(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8"))
128
- value = data["choices"][0]["message"]["content"]
129
- if not isinstance(value, str):
130
- raise ValueError
131
- except (KeyError, IndexError, TypeError, ValueError, json.JSONDecodeError):
132
- raise SystemExit(2)
133
- print(value)
134
- PY
135
- ) || { printf '%s\n' 'Error: invalid vision API response (body redacted)' >&2; exit 1; }
136
-
137
- printf '%s\n' "$result"