@boyingliu01/xp-gate 0.18.4 → 0.19.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.
Files changed (248) hide show
  1. package/adapter-common.sh +27 -0
  2. package/adapters/powershell.sh +85 -33
  3. package/adapters/typescript.sh +8 -8
  4. package/build-integrity/__tests__/import-resolver.test.ts +22 -0
  5. package/build-integrity/__tests__/orchestrator.test.ts +1 -2
  6. package/build-integrity/gate-10.ts +7 -0
  7. package/gate-12-file-hygiene.sh +230 -0
  8. package/hooks/adapter-common.sh +27 -0
  9. package/hooks/gate-10.sh +105 -0
  10. package/hooks/lib/validate-code-walkthrough.cjs +125 -0
  11. package/hooks/pre-commit +130 -33
  12. package/hooks/pre-push +15 -91
  13. package/lib/__tests__/check-version.test.js +67 -46
  14. package/lib/__tests__/doctor.test.js +7 -6
  15. package/lib/__tests__/gate-runner.test.js +267 -0
  16. package/lib/__tests__/init.test.js +32 -0
  17. package/lib/__tests__/npm-package.test.js +13 -0
  18. package/lib/__tests__/phase-transition.test.js +604 -12
  19. package/lib/__tests__/sprint-discovery.test.ts +0 -1
  20. package/lib/__tests__/sprint-status-rework.test.js +100 -1
  21. package/lib/__tests__/update-hooks.test.js +143 -10
  22. package/lib/__tests__/upgrade-exec.test.js +73 -45
  23. package/lib/__tests__/upgrade-skill-sync.test.js +1 -1
  24. package/lib/__tests__/upgrade.test.js +12 -11
  25. package/lib/doctor.js +2 -1
  26. package/lib/gate-runner.js +68 -23
  27. package/lib/init.js +34 -5
  28. package/lib/install-skill.js +1 -0
  29. package/lib/mattpocock-license-verdict.json +1 -1
  30. package/lib/phase-transition.js +203 -23
  31. package/lib/shared-paths.js +2 -0
  32. package/lib/sprint-status.js +15 -4
  33. package/lib/test-alignment.ts +3 -13
  34. package/lib/update-hooks.js +129 -15
  35. package/mock-policy/AGENTS.md +5 -5
  36. package/mock-policy/__tests__/gate-m3.test.ts +0 -5
  37. package/mock-policy/__tests__/scope-scanner.test.ts +8 -2
  38. package/mutation/AGENTS.md +4 -4
  39. package/mutation/__tests__/mutmut-runner.test.ts +443 -2
  40. package/mutation/__tests__/update-baseline.test.ts +0 -2
  41. package/mutation/runners/mutmut-runner.ts +67 -17
  42. package/package.json +9 -3
  43. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  44. package/plugins/claude-code/skills/clipboard-vision/SKILL.md +47 -0
  45. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  46. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  47. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  48. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  49. package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  50. package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.sh +161 -0
  51. package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  52. package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  53. package/plugins/claude-code/skills/delphi-review/.delphi-config.json.example +24 -27
  54. package/plugins/claude-code/skills/delphi-review/AGENTS.md +13 -12
  55. package/plugins/claude-code/skills/delphi-review/INSTALL.md +15 -17
  56. package/plugins/claude-code/skills/delphi-review/SKILL.md +30 -29
  57. package/plugins/claude-code/skills/delphi-review/opencode.json.delphi.example +6 -10
  58. package/plugins/claude-code/skills/delphi-review/references/code-walkthrough.md +33 -49
  59. package/plugins/claude-code/skills/delphi-review/references/requirements.md +66 -54
  60. package/plugins/claude-code/skills/delphi-review/references/round-templates.md +7 -7
  61. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +5 -5
  62. package/plugins/claude-code/skills/sprint-flow/SKILL.md +4 -4
  63. package/plugins/claude-code/skills/sprint-flow/references/components/skill-invocations.md +2 -2
  64. package/plugins/claude-code/skills/sprint-flow/references/force-levels.md +37 -35
  65. package/plugins/claude-code/skills/sprint-flow/references/orchestration-rules.md +1 -1
  66. package/plugins/claude-code/skills/sprint-flow/references/phase-1-prep.md +1 -1
  67. package/plugins/claude-code/skills/sprint-flow/references/phase-2-design.md +24 -14
  68. package/plugins/claude-code/skills/sprint-flow/references/phase-4-verify.md +6 -6
  69. package/plugins/claude-code/skills/sprint-flow/references/phase-overview.md +2 -2
  70. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +4 -4
  71. package/plugins/dsh/README.md +25 -0
  72. package/plugins/dsh/cordis.patch.yml +7 -0
  73. package/plugins/dsh/package.json +70 -0
  74. package/plugins/dsh/scripts/prepack.cjs +82 -0
  75. package/plugins/dsh/skills/admin-template-guidelines/SKILL.md +113 -0
  76. package/plugins/dsh/skills/admin-template-guidelines/references/rule-1.md +91 -0
  77. package/plugins/dsh/skills/admin-template-guidelines/references/rule-2.md +155 -0
  78. package/plugins/dsh/skills/admin-template-guidelines/references/rule-3.md +70 -0
  79. package/plugins/dsh/skills/admin-template-guidelines/references/rule-4.md +154 -0
  80. package/plugins/dsh/skills/admin-template-guidelines/references/rule-5.md +126 -0
  81. package/plugins/dsh/skills/admin-template-guidelines/references/rule-6.md +180 -0
  82. package/plugins/dsh/skills/batch-grill-me/SKILL.md +15 -0
  83. package/plugins/dsh/skills/clipboard-vision/SKILL.md +47 -0
  84. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  85. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  86. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  87. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  88. package/plugins/dsh/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  89. package/plugins/dsh/skills/clipboard-vision/describe-clipboard.sh +161 -0
  90. package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  91. package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  92. package/plugins/dsh/skills/delphi-review/.delphi-config.json.example +70 -0
  93. package/plugins/dsh/skills/delphi-review/AGENTS.md +67 -0
  94. package/plugins/dsh/skills/delphi-review/INSTALL.md +150 -0
  95. package/plugins/dsh/skills/delphi-review/SKILL.md +559 -0
  96. package/plugins/dsh/skills/delphi-review/hooks.md +19 -0
  97. package/plugins/dsh/skills/delphi-review/opencode.json.delphi.example +52 -0
  98. package/plugins/dsh/skills/delphi-review/references/code-walkthrough.md +470 -0
  99. package/plugins/dsh/skills/delphi-review/references/orchestrator-dispatch.md +64 -0
  100. package/plugins/dsh/skills/delphi-review/references/requirements.md +402 -0
  101. package/plugins/dsh/skills/delphi-review/references/round-templates.md +134 -0
  102. package/plugins/dsh/skills/delphi-review/scripts/verify-consensus.sh +43 -0
  103. package/plugins/dsh/skills/delphi-review/tools.md +29 -0
  104. package/plugins/dsh/skills/domain-modeling/ADR-FORMAT.md +64 -0
  105. package/plugins/dsh/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  106. package/plugins/dsh/skills/domain-modeling/SKILL.md +74 -0
  107. package/plugins/dsh/skills/grill-with-docs/SKILL.md +7 -0
  108. package/plugins/dsh/skills/grilling/SKILL.md +12 -0
  109. package/plugins/dsh/skills/improve-codebase-architecture/SKILL.md +156 -0
  110. package/plugins/dsh/skills/ralph-loop/SKILL.md +198 -0
  111. package/plugins/dsh/skills/ralph-loop/references/components.md +113 -0
  112. package/plugins/dsh/skills/ralph-loop/references/phase-2-build-ralph.md +89 -0
  113. package/plugins/dsh/skills/ralph-loop/references/workflow-details.md +99 -0
  114. package/plugins/dsh/skills/ralph-loop/templates/progress-log.md +36 -0
  115. package/plugins/dsh/skills/sprint-flow/AGENTS.md +103 -0
  116. package/plugins/dsh/skills/sprint-flow/SKILL.md +411 -0
  117. package/plugins/dsh/skills/sprint-flow/__tests__/sprint-flow.test.cjs +457 -0
  118. package/plugins/dsh/skills/sprint-flow/hooks.md +18 -0
  119. package/plugins/dsh/skills/sprint-flow/references/components/memory.md +87 -0
  120. package/plugins/dsh/skills/sprint-flow/references/components/middleware.md +75 -0
  121. package/plugins/dsh/skills/sprint-flow/references/components/skill-invocations.md +105 -0
  122. package/plugins/dsh/skills/sprint-flow/references/components/system-prompt.md +27 -0
  123. package/plugins/dsh/skills/sprint-flow/references/components/tool-descriptions.md +95 -0
  124. package/plugins/dsh/skills/sprint-flow/references/force-levels.md +204 -0
  125. package/plugins/dsh/skills/sprint-flow/references/orchestration-rules.md +236 -0
  126. package/plugins/dsh/skills/sprint-flow/references/phase-1-prep.md +294 -0
  127. package/plugins/dsh/skills/sprint-flow/references/phase-2-design.md +273 -0
  128. package/plugins/dsh/skills/sprint-flow/references/phase-3-build.md +348 -0
  129. package/plugins/dsh/skills/sprint-flow/references/phase-4-verify.md +225 -0
  130. package/plugins/dsh/skills/sprint-flow/references/phase-5-ship.md +222 -0
  131. package/plugins/dsh/skills/sprint-flow/references/phase-6-close.md +266 -0
  132. package/plugins/dsh/skills/sprint-flow/references/phase-overview.md +486 -0
  133. package/plugins/dsh/skills/sprint-flow/scripts/verify-sprint-state.sh +38 -0
  134. package/plugins/dsh/skills/sprint-flow/templates/auto-estimate-learning-log.md +136 -0
  135. package/plugins/dsh/skills/sprint-flow/templates/auto-estimate-output-template.md +110 -0
  136. package/plugins/dsh/skills/sprint-flow/templates/emergent-issues-template.md +120 -0
  137. package/plugins/dsh/skills/sprint-flow/templates/pain-document-template.md +115 -0
  138. package/plugins/dsh/skills/sprint-flow/templates/sprint-progress-template.md +140 -0
  139. package/plugins/dsh/skills/sprint-flow/templates/sprint-summary-template.md +121 -0
  140. package/plugins/dsh/skills/sprint-flow/tools.md +29 -0
  141. package/plugins/dsh/skills/test-driven-development/SKILL.md +371 -0
  142. package/plugins/dsh/skills/test-driven-development/testing-anti-patterns.md +299 -0
  143. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +56 -0
  144. package/plugins/dsh/skills/test-specification-alignment/SKILL.md +205 -0
  145. package/plugins/dsh/skills/test-specification-alignment/references/alignment-verification-algorithm.md +493 -0
  146. package/plugins/dsh/skills/test-specification-alignment/references/phase2-constraint-enforcement.md +431 -0
  147. package/plugins/dsh/skills/test-specification-alignment/references/specification-format.md +348 -0
  148. package/plugins/dsh/skills/to-issues/SKILL.md +277 -0
  149. package/plugins/dsh/src/command.test.ts +102 -0
  150. package/plugins/dsh/src/command.ts +75 -0
  151. package/plugins/dsh/src/contract.test.ts +62 -0
  152. package/plugins/dsh/src/gate-runner.test.ts +100 -0
  153. package/plugins/dsh/src/gate-runner.ts +58 -0
  154. package/plugins/dsh/src/index.test.ts +97 -0
  155. package/plugins/dsh/src/index.ts +94 -0
  156. package/plugins/dsh/src/skills.test.ts +58 -0
  157. package/plugins/dsh/tsconfig.build.json +13 -0
  158. package/plugins/dsh/tsconfig.json +19 -0
  159. package/plugins/dsh/vitest.config.ts +8 -0
  160. package/plugins/opencode/package.json +1 -1
  161. package/plugins/opencode/scripts/prepack.cjs +1 -0
  162. package/plugins/opencode/skills/clipboard-vision/SKILL.md +47 -0
  163. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  164. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  165. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  166. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  167. package/plugins/opencode/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  168. package/plugins/opencode/skills/clipboard-vision/describe-clipboard.sh +161 -0
  169. package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  170. package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  171. package/plugins/opencode/skills/delphi-review/.delphi-config.json.example +24 -27
  172. package/plugins/opencode/skills/delphi-review/AGENTS.md +13 -12
  173. package/plugins/opencode/skills/delphi-review/INSTALL.md +15 -17
  174. package/plugins/opencode/skills/delphi-review/SKILL.md +30 -29
  175. package/plugins/opencode/skills/delphi-review/opencode.json.delphi.example +6 -10
  176. package/plugins/opencode/skills/delphi-review/references/code-walkthrough.md +33 -49
  177. package/plugins/opencode/skills/delphi-review/references/requirements.md +66 -54
  178. package/plugins/opencode/skills/delphi-review/references/round-templates.md +7 -7
  179. package/plugins/opencode/skills/sprint-flow/AGENTS.md +5 -5
  180. package/plugins/opencode/skills/sprint-flow/SKILL.md +4 -4
  181. package/plugins/opencode/skills/sprint-flow/references/components/skill-invocations.md +2 -2
  182. package/plugins/opencode/skills/sprint-flow/references/force-levels.md +37 -35
  183. package/plugins/opencode/skills/sprint-flow/references/orchestration-rules.md +1 -1
  184. package/plugins/opencode/skills/sprint-flow/references/phase-1-prep.md +1 -1
  185. package/plugins/opencode/skills/sprint-flow/references/phase-2-design.md +24 -14
  186. package/plugins/opencode/skills/sprint-flow/references/phase-4-verify.md +6 -6
  187. package/plugins/opencode/skills/sprint-flow/references/phase-overview.md +2 -2
  188. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +4 -4
  189. package/plugins/qoder/plugin.json +1 -1
  190. package/plugins/qoder/skills/clipboard-vision/SKILL.md +47 -0
  191. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  192. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  193. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  194. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  195. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/SKILL.md +47 -0
  196. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  197. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  198. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  199. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  200. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  201. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  202. package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  203. package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  204. package/plugins/qoder/skills/delphi-review/.delphi-config.json.example +3 -11
  205. package/plugins/qoder/skills/delphi-review/AGENTS.md +15 -17
  206. package/plugins/qoder/skills/delphi-review/INSTALL.md +12 -12
  207. package/plugins/qoder/skills/delphi-review/SKILL.md +58 -25
  208. package/plugins/qoder/skills/delphi-review/opencode.json.delphi.example +1 -1
  209. package/plugins/qoder/skills/delphi-review/references/code-walkthrough.md +33 -49
  210. package/plugins/qoder/skills/sprint-flow/AGENTS.md +5 -5
  211. package/plugins/qoder/skills/sprint-flow/SKILL.md +2 -2
  212. package/plugins/qoder/skills/sprint-flow/references/force-levels.md +38 -35
  213. package/plugins/qoder/skills/sprint-flow/references/phase-1-prep.md +1 -1
  214. package/plugins/qoder/skills/sprint-flow/references/phase-2-design.md +48 -6
  215. package/plugins/qoder/skills/sprint-flow/references/phase-4-verify.md +5 -6
  216. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +4 -4
  217. package/principles/AGENTS.md +4 -4
  218. package/scripts/__tests__/sync-package-content.test.js +30 -0
  219. package/scripts/delphi-external-review.cjs +194 -63
  220. package/scripts/sync-package-content.js +9 -2
  221. package/skills/clipboard-vision/SKILL.md +47 -0
  222. package/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  223. package/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  224. package/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  225. package/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  226. package/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  227. package/skills/clipboard-vision/describe-clipboard.sh +161 -0
  228. package/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  229. package/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  230. package/skills/delphi-review/.delphi-config.json.example +24 -27
  231. package/skills/delphi-review/AGENTS.md +13 -12
  232. package/skills/delphi-review/INSTALL.md +15 -17
  233. package/skills/delphi-review/SKILL.md +30 -29
  234. package/skills/delphi-review/opencode.json.delphi.example +6 -10
  235. package/skills/delphi-review/references/code-walkthrough.md +33 -49
  236. package/skills/delphi-review/references/requirements.md +66 -54
  237. package/skills/delphi-review/references/round-templates.md +7 -7
  238. package/skills/sprint-flow/AGENTS.md +5 -5
  239. package/skills/sprint-flow/SKILL.md +4 -4
  240. package/skills/sprint-flow/references/components/skill-invocations.md +2 -2
  241. package/skills/sprint-flow/references/force-levels.md +37 -35
  242. package/skills/sprint-flow/references/orchestration-rules.md +1 -1
  243. package/skills/sprint-flow/references/phase-1-prep.md +1 -1
  244. package/skills/sprint-flow/references/phase-2-design.md +24 -14
  245. package/skills/sprint-flow/references/phase-4-verify.md +6 -6
  246. package/skills/sprint-flow/references/phase-overview.md +2 -2
  247. package/skills/test-specification-alignment/AGENTS.md +4 -4
  248. package/sprint-gate.sh +291 -0
@@ -0,0 +1,137 @@
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"
@@ -0,0 +1,86 @@
1
+ [CmdletBinding()]
2
+ param(
3
+ [switch]$AllowRemote,
4
+ [string]$ConfirmRemote
5
+ )
6
+
7
+ $ErrorActionPreference = 'Stop'
8
+ $ApiBase = if ($env:CLIPBOARD_VISION_API_BASE) { $env:CLIPBOARD_VISION_API_BASE } else { 'http://127.0.0.1:11434/v1' }
9
+ $Model = $env:CLIPBOARD_VISION_MODEL
10
+ $ApiKey = $env:CLIPBOARD_VISION_API_KEY
11
+ $MaxBytes = if ($env:CLIPBOARD_VISION_MAX_BYTES) { [long]$env:CLIPBOARD_VISION_MAX_BYTES } else { 10485760 }
12
+
13
+ if (-not $Model) { throw 'CLIPBOARD_VISION_MODEL is required' }
14
+ if ($MaxBytes -le 0) { throw 'CLIPBOARD_VISION_MAX_BYTES must be positive' }
15
+ $Endpoint = $null
16
+ if (-not [Uri]::TryCreate($ApiBase, [UriKind]::Absolute, [ref]$Endpoint) -or
17
+ -not $Endpoint.IsAbsoluteUri -or
18
+ $Endpoint.Scheme -notin @('http', 'https') -or
19
+ $Endpoint.UserInfo.Length -ne 0 -or
20
+ $Endpoint.Query.Length -ne 0 -or
21
+ $Endpoint.Fragment.Length -ne 0) {
22
+ throw 'CLIPBOARD_VISION_API_BASE must be an absolute HTTP(S) URI without credentials'
23
+ }
24
+ $Address = $null
25
+ $LiteralAddress = [Net.IPAddress]::TryParse($Endpoint.Host.Trim('[', ']'), [ref]$Address)
26
+ $Loopback = $LiteralAddress -and [Net.IPAddress]::IsLoopback($Address)
27
+ $NormalizedHost = $Endpoint.Host.Trim('[', ']').ToLowerInvariant()
28
+ $EffectivePort = if ($Endpoint.IsDefaultPort) { if ($Endpoint.Scheme -eq 'https') { 443 } else { 80 } } else { $Endpoint.Port }
29
+ $DisplayHost = if ($NormalizedHost.Contains(':')) { "[$NormalizedHost]" } else { $NormalizedHost }
30
+ $BasePath = $Endpoint.AbsolutePath.TrimEnd('/')
31
+ $EffectiveEndpoint = "$($Endpoint.Scheme.ToLowerInvariant())://$DisplayHost`:$EffectivePort$BasePath/chat/completions"
32
+ if (-not $Loopback) {
33
+ $ConsentBytes = [Text.Encoding]::UTF8.GetBytes("$EffectiveEndpoint`n$Model")
34
+ $Hasher = [Security.Cryptography.SHA256]::Create()
35
+ try { $ExpectedConfirmation = ([BitConverter]::ToString($Hasher.ComputeHash($ConsentBytes))).Replace('-', '').ToLowerInvariant() } finally { $Hasher.Dispose() }
36
+ [Console]::Error.WriteLine("Remote disclosure: clipboard image data will be sent to $EffectiveEndpoint using model $Model.")
37
+ [Console]::Error.WriteLine("Confirmation token for this canonical endpoint and model: $ExpectedConfirmation")
38
+ if (-not $AllowRemote -or $ConfirmRemote -cne $ExpectedConfirmation) {
39
+ throw 'Remote endpoint requires -AllowRemote and the disclosed -ConfirmRemote token'
40
+ }
41
+ }
42
+
43
+ $TempDirectory = Join-Path ([IO.Path]::GetTempPath()) ("clipboard-vision-" + [Guid]::NewGuid())
44
+ $ImagePath = Join-Path $TempDirectory 'clipboard.png'
45
+ try {
46
+ New-Item -ItemType Directory -Path $TempDirectory | Out-Null
47
+ if ($env:CLIPBOARD_VISION_TEST_IMAGE) {
48
+ Copy-Item -LiteralPath $env:CLIPBOARD_VISION_TEST_IMAGE -Destination $ImagePath
49
+ } else {
50
+ Add-Type -AssemblyName System.Windows.Forms
51
+ Add-Type -AssemblyName System.Drawing
52
+ $Image = [Windows.Forms.Clipboard]::GetImage()
53
+ if ($null -eq $Image) { throw 'Clipboard does not contain an image' }
54
+ try { $Image.Save($ImagePath, [Drawing.Imaging.ImageFormat]::Png) } finally { $Image.Dispose() }
55
+ }
56
+ if ((Get-Item $ImagePath).Length -gt $MaxBytes) { throw "Clipboard image exceeds $MaxBytes bytes" }
57
+
58
+ $Encoded = [Convert]::ToBase64String([IO.File]::ReadAllBytes($ImagePath))
59
+ $Body = @{
60
+ model = $Model
61
+ messages = @(@{ role = 'user'; content = @(
62
+ @{ type = 'text'; text = 'Describe this clipboard image.' },
63
+ @{ type = 'image_url'; image_url = @{ url = "data:image/png;base64,$Encoded" } }
64
+ ) })
65
+ } | ConvertTo-Json -Depth 8 -Compress
66
+ $Headers = @{}
67
+ if ($ApiKey) { $Headers.Authorization = "Bearer $ApiKey" }
68
+ try {
69
+ if ($env:CLIPBOARD_VISION_TEST_HTTP_CAPTURE) {
70
+ Set-Content -LiteralPath $env:CLIPBOARD_VISION_TEST_HTTP_CAPTURE -Value $Body -Encoding utf8
71
+ if ($env:CV_TEST_HTTP_FAILURE) { throw 'test HTTP failure body secret' }
72
+ if ($env:CV_TEST_MALFORMED_JSON) { $Response = $null }
73
+ elseif ($env:CV_TEST_NON_STRING) { $Response = @{ choices = @(@{ message = @{ content = @{ value = 1 } } }) } }
74
+ else { $Response = @{ choices = @(@{ message = @{ content = 'test description' } }) } }
75
+ } else {
76
+ $Response = Invoke-RestMethod -Method Post -Uri $EffectiveEndpoint -Headers $Headers -ContentType 'application/json' -Body $Body -MaximumRedirection 0
77
+ }
78
+ } catch {
79
+ throw 'Vision API request failed (response body redacted)'
80
+ }
81
+ $Result = $Response.choices[0].message.content
82
+ if ($Result -isnot [string]) { throw 'Invalid vision API response (body redacted)' }
83
+ $Result
84
+ } finally {
85
+ Remove-Item -LiteralPath $TempDirectory -Recurse -Force -ErrorAction SilentlyContinue
86
+ }
@@ -0,0 +1,137 @@
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"
@@ -4,15 +4,7 @@
4
4
  "description": "Delphi review expert mapping — customize with your own models. Copy to .delphi-config.json and edit.",
5
5
  "num_experts": 3,
6
6
  "model_policy": {
7
- "domestic_only": true,
8
- "description": "Only domestic Chinese open-source models are allowed. NEVER use Anthropic, OpenAI, Google, or other foreign expensive models.",
9
- "allowed_models": [
10
- "glm-5.1", "glm-5.0",
11
- "kimi-k2.6", "kimi-k2.5",
12
- "minimax-m2.7", "minimax-m2.5",
13
- "qwen3.6-plus", "qwen3.5-plus",
14
- "deepseek-v4-pro", "deepseek-v4-lite"
15
- ]
7
+ "description": "Provider, vendor, gateway, and model nationality are unrestricted. Three distinct trimmed executable model IDs are required."
16
8
  },
17
9
  "experts": {
18
10
  "architecture": {
@@ -38,8 +30,8 @@
38
30
  }
39
31
  },
40
32
  "consensus": {
41
- "threshold_percent": 95,
33
+ "threshold_percent": 90,
42
34
  "max_review_rounds": 5,
43
- "cross_provider_required": true
35
+ "distinct_models_required": true
44
36
  }
45
37
  }
@@ -1,12 +1,12 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-07-29
4
- **Commit:** 527fca8
5
- **Branch:** main
6
- **Version:** 0.18.3.0
3
+ **Generated:** 2026-08-24
4
+ **Commit:** a1a4683
5
+ **Branch:** dsh-plugin
6
+ **Version:** 0.19.0.0
7
7
 
8
8
  ## OVERVIEW
9
- Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
9
+ Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
10
10
 
11
11
  ## STRUCTURE
12
12
  ```
@@ -25,19 +25,16 @@ skills/delphi-review/
25
25
  | Task | Location | Notes |
26
26
  |------|----------|-------|
27
27
  | Core methodology | SKILL.md | Delphi process, expert roles, consensus rules |
28
- | Code-walkthrough | references/code-walkthrough.md | Pre-push mode: 20 files/500 LOC limit |
29
- | Config example | .delphi-config.json.example | 3 experts, providers + API keys |
30
- | External API script | scripts/delphi-external-review.cjs | Calls model APIs, returns JSON verdict |
28
+ | Code-walkthrough | references/code-walkthrough.md | Pre-push mode: complete review evidence with no hard file/LOC threshold |
29
+ | Config example | .delphi-config.json.example | 3 experts, distinct models |
31
30
 
32
31
  ## CONVENTIONS
33
32
  - 3 experts anonymous in Round 1 (no cross-expert bias)
34
33
  - ≥90% consensus threshold (was 95%, now unified to 90%)
35
34
  - Max 5 rounds before forcing decision
36
- - Cross-provider required: experts from ≥2 different providers (config read from `.delphi-config.json`, not hardcoded)
37
- - Model selection: reads provider/model from `.delphi-config.json` active profile
38
- - Mixed mode: `provider: "local"` falls back to orchestrator model (reduced diversity warning)
39
- - No hardcoded model lists — models defined by user's `.delphi-config.json` configuration
40
- - Execution: via Bash tool calling `delphi-external-review.cjs` script (not subagent dispatch)
35
+ - Provider/vendor/nationality unrestricted; exactly three distinct trimmed requested model IDs are required
36
+ - Model selection: reads `delphi-reviewer-*` agent `model` fields from `opencode.json`
37
+ - No hardcoded model lists — models defined by user's `opencode.json` configuration
41
38
  - Code-walkthrough mode: triggered on git push, stores result in .code-walkthrough-result.json
42
39
  - Code-walkthrough skipped on main/master pushes (by design)
43
40
 
@@ -45,25 +42,26 @@ skills/delphi-review/
45
42
  - Do NOT terminate before achieving true consensus (≥90%)
46
43
  - Do NOT reveal other experts' opinions during Round 1
47
44
  - Do NOT accept partial agreement without resolution
48
- - Do NOT skip code-walkthrough when over thresholds (BLOCK + user decision)
45
+ - Do NOT auto-skip or bypass code-walkthrough based on change size; review large diffs completely or split them by user choice
49
46
  - Do NOT degrade to single model on API errors (BLOCK)
50
47
  - Do NOT declare complete without writing .code-walkthrough-result.json
51
- - Do NOT use foreign models (Anthropic/GPT/Gemini)
48
+ - Do NOT treat `provider: local` fallback as an executed expert
52
49
 
53
50
  ## UNIQUE STYLES
54
51
  - Anonymous expert reviews (Round 1)
55
52
  - Statistical consensus measurement (≥90% threshold)
56
- - Two modes: design review + code-walkthrough
53
+ - Three modes: requirements review + design review + code-walkthrough
57
54
  - Pre-push integration: .code-walkthrough-result.json stores commit hash + verdict
58
55
  - Delphi guard in claude-code plugin: blocks Edit/Write before APPROVAL
59
56
 
60
57
  ## COMMANDS
61
58
  ```bash
62
59
  /delphi-review # Design review mode
60
+ /delphi-review --mode requirements # Phase 2 R1 requirements review
63
61
  /delphi-review --mode code-walkthrough # Pre-push code walkthrough
64
62
  ```
65
63
 
66
64
  ## NOTES
67
65
  - Used by pre-push hook for code-walkthrough validation
68
66
  - Delphi guard (claude-code plugin) reads .sprint-state/delphi-reviewed.json
69
- - Code-walkthrough result must match commit hash for verification
67
+ - Code-walkthrough result must match commit hash for verification
@@ -5,10 +5,10 @@ This guide walks you through setting up the Delphi consensus review skill in you
5
5
  ## Prerequisites
6
6
 
7
7
  - **Node.js >= 18** (script uses built-in `fetch`)
8
- - At least **2 different model providers** with API access (cross-provider requirement prevents homogenized blind spots)
8
+ - Exactly **3 callable expert model configurations** with distinct trimmed executable model IDs
9
9
  - `@boyingliu01/xp-gate` npm package installed (for the `delphi-external-review.cjs` script)
10
10
 
11
- > **Why cross-provider?** Using models from the same vendor means they share training data and biases, defeating the purpose of multi-expert consensus.
11
+ > Provider, vendor, gateway, and model nationality are unrestricted. One provider and token plan may serve all three roles.
12
12
 
13
13
  ## Quick Setup (4 steps)
14
14
 
@@ -47,7 +47,7 @@ Open `.delphi-config.json` and fill in your API keys and model preferences:
47
47
  "experts": {
48
48
  "architecture": { "provider": "deepseek", "model": "deepseek-chat" },
49
49
  "technical": { "provider": "zhipu", "model": "glm-5.2" },
50
- "feasibility": { "provider": "local" }
50
+ "feasibility": { "provider": "deepseek", "model": "deepseek-reasoner" }
51
51
  }
52
52
  }
53
53
  }
@@ -82,7 +82,7 @@ Where `<script-path>` is located (in priority order):
82
82
  | `profiles` | ✅ | Named configuration profiles (for easy switching) |
83
83
  | `profiles.<name>.providers` | ✅ | Provider definitions: base_url + api_key |
84
84
  | `profiles.<name>.experts` | ✅ | Expert-to-provider/model mapping |
85
- | `profiles.<name>.experts.<role>.provider` | ✅ | Provider name, or `"local"` for orchestrator fallback |
85
+ | `profiles.<name>.experts.<role>.provider` | ✅ | Callable provider name; `"local"` fallback cannot count |
86
86
  | `consensus.threshold_percent` | ❌ | Consensus threshold (default: 90) |
87
87
  | `consensus.max_review_rounds` | ❌ | Max review rounds (default: 5) |
88
88
 
@@ -90,9 +90,9 @@ Where `<script-path>` is located (in priority order):
90
90
 
91
91
  Edit `active_profile` in the config, or use the `--profile <name>` CLI argument to override temporarily.
92
92
 
93
- ### Mixed mode (gradual setup)
93
+ ### Single-provider setup
94
94
 
95
- You can start with just 1 external API and use the orchestrator model for other experts:
95
+ One provider may expose all three distinct executable models:
96
96
 
97
97
  ```json
98
98
  {
@@ -104,15 +104,15 @@ You can start with just 1 external API and use the orchestrator model for other
104
104
  },
105
105
  "experts": {
106
106
  "architecture": { "provider": "deepseek", "model": "deepseek-chat" },
107
- "technical": { "provider": "local" },
108
- "feasibility": { "provider": "local" }
107
+ "technical": { "provider": "deepseek", "model": "deepseek-reasoner" },
108
+ "feasibility": { "provider": "deepseek", "model": "deepseek-coder" }
109
109
  }
110
110
  }
111
111
  }
112
112
  }
113
113
  ```
114
114
 
115
- > This works but produces a WARNING about reduced cross-model diversity. Add more external APIs over time.
115
+ > All three model IDs must remain distinct after trimming, and all three calls must succeed.
116
116
 
117
117
  ## Usage
118
118
 
@@ -125,7 +125,7 @@ Once configured, invoke the skill via:
125
125
  The skill will:
126
126
  1. Read `.delphi-config.json` to find expert configurations
127
127
  2. Call external model APIs via `delphi-external-review.cjs` script
128
- 3. For `provider: "local"` experts, use the orchestrator model
128
+ 3. Reject `provider: "local"` fallback as non-executed evidence
129
129
  4. Aggregate verdicts and compute consensus
130
130
 
131
131
  ## Troubleshooting
@@ -142,9 +142,9 @@ Install the npm package: `npm install -g @boyingliu01/xp-gate`
142
142
 
143
143
  Check your API key in `.delphi-config.json`. Ensure the key matches the provider.
144
144
 
145
- ### "All experts use the same provider"
145
+ ### "Expert model IDs are not distinct"
146
146
 
147
- Configure at least 2 different providers, or use `provider: "local"` for mixed mode.
147
+ Configure three distinct callable model IDs. They may use the same provider.
148
148
 
149
149
  ### "Node.js >= 18 required"
150
150