@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.
- package/adapter-common.sh +27 -0
- package/adapters/powershell.sh +85 -33
- package/adapters/typescript.sh +8 -8
- package/build-integrity/__tests__/import-resolver.test.ts +22 -0
- package/build-integrity/__tests__/orchestrator.test.ts +1 -2
- package/build-integrity/gate-10.ts +7 -0
- package/gate-12-file-hygiene.sh +230 -0
- package/hooks/adapter-common.sh +27 -0
- package/hooks/gate-10.sh +105 -0
- package/hooks/lib/validate-code-walkthrough.cjs +125 -0
- package/hooks/pre-commit +130 -33
- package/hooks/pre-push +15 -91
- package/lib/__tests__/check-version.test.js +67 -46
- package/lib/__tests__/doctor.test.js +7 -6
- package/lib/__tests__/gate-runner.test.js +267 -0
- package/lib/__tests__/init.test.js +32 -0
- package/lib/__tests__/npm-package.test.js +13 -0
- package/lib/__tests__/phase-transition.test.js +604 -12
- package/lib/__tests__/sprint-discovery.test.ts +0 -1
- package/lib/__tests__/sprint-status-rework.test.js +100 -1
- package/lib/__tests__/update-hooks.test.js +143 -10
- package/lib/__tests__/upgrade-exec.test.js +73 -45
- package/lib/__tests__/upgrade-skill-sync.test.js +1 -1
- package/lib/__tests__/upgrade.test.js +12 -11
- package/lib/doctor.js +2 -1
- package/lib/gate-runner.js +68 -23
- package/lib/init.js +34 -5
- package/lib/install-skill.js +1 -0
- package/lib/mattpocock-license-verdict.json +1 -1
- package/lib/phase-transition.js +203 -23
- package/lib/shared-paths.js +2 -0
- package/lib/sprint-status.js +15 -4
- package/lib/test-alignment.ts +3 -13
- package/lib/update-hooks.js +129 -15
- package/mock-policy/AGENTS.md +5 -5
- package/mock-policy/__tests__/gate-m3.test.ts +0 -5
- package/mock-policy/__tests__/scope-scanner.test.ts +8 -2
- package/mutation/AGENTS.md +4 -4
- package/mutation/__tests__/mutmut-runner.test.ts +443 -2
- package/mutation/__tests__/update-baseline.test.ts +0 -2
- package/mutation/runners/mutmut-runner.ts +67 -17
- package/package.json +9 -3
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/clipboard-vision/SKILL.md +47 -0
- package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
- package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
- package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
- package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
- package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
- package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.sh +161 -0
- package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
- package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
- package/plugins/claude-code/skills/delphi-review/.delphi-config.json.example +24 -27
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +13 -12
- package/plugins/claude-code/skills/delphi-review/INSTALL.md +15 -17
- package/plugins/claude-code/skills/delphi-review/SKILL.md +30 -29
- package/plugins/claude-code/skills/delphi-review/opencode.json.delphi.example +6 -10
- package/plugins/claude-code/skills/delphi-review/references/code-walkthrough.md +33 -49
- package/plugins/claude-code/skills/delphi-review/references/requirements.md +66 -54
- package/plugins/claude-code/skills/delphi-review/references/round-templates.md +7 -7
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +5 -5
- package/plugins/claude-code/skills/sprint-flow/SKILL.md +4 -4
- package/plugins/claude-code/skills/sprint-flow/references/components/skill-invocations.md +2 -2
- package/plugins/claude-code/skills/sprint-flow/references/force-levels.md +37 -35
- package/plugins/claude-code/skills/sprint-flow/references/orchestration-rules.md +1 -1
- package/plugins/claude-code/skills/sprint-flow/references/phase-1-prep.md +1 -1
- package/plugins/claude-code/skills/sprint-flow/references/phase-2-design.md +24 -14
- package/plugins/claude-code/skills/sprint-flow/references/phase-4-verify.md +6 -6
- package/plugins/claude-code/skills/sprint-flow/references/phase-overview.md +2 -2
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +4 -4
- package/plugins/dsh/README.md +25 -0
- package/plugins/dsh/cordis.patch.yml +7 -0
- package/plugins/dsh/package.json +70 -0
- package/plugins/dsh/scripts/prepack.cjs +82 -0
- package/plugins/dsh/skills/admin-template-guidelines/SKILL.md +113 -0
- package/plugins/dsh/skills/admin-template-guidelines/references/rule-1.md +91 -0
- package/plugins/dsh/skills/admin-template-guidelines/references/rule-2.md +155 -0
- package/plugins/dsh/skills/admin-template-guidelines/references/rule-3.md +70 -0
- package/plugins/dsh/skills/admin-template-guidelines/references/rule-4.md +154 -0
- package/plugins/dsh/skills/admin-template-guidelines/references/rule-5.md +126 -0
- package/plugins/dsh/skills/admin-template-guidelines/references/rule-6.md +180 -0
- package/plugins/dsh/skills/batch-grill-me/SKILL.md +15 -0
- package/plugins/dsh/skills/clipboard-vision/SKILL.md +47 -0
- package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
- package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
- package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
- package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
- package/plugins/dsh/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
- package/plugins/dsh/skills/clipboard-vision/describe-clipboard.sh +161 -0
- package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
- package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
- package/plugins/dsh/skills/delphi-review/.delphi-config.json.example +70 -0
- package/plugins/dsh/skills/delphi-review/AGENTS.md +67 -0
- package/plugins/dsh/skills/delphi-review/INSTALL.md +150 -0
- package/plugins/dsh/skills/delphi-review/SKILL.md +559 -0
- package/plugins/dsh/skills/delphi-review/hooks.md +19 -0
- package/plugins/dsh/skills/delphi-review/opencode.json.delphi.example +52 -0
- package/plugins/dsh/skills/delphi-review/references/code-walkthrough.md +470 -0
- package/plugins/dsh/skills/delphi-review/references/orchestrator-dispatch.md +64 -0
- package/plugins/dsh/skills/delphi-review/references/requirements.md +402 -0
- package/plugins/dsh/skills/delphi-review/references/round-templates.md +134 -0
- package/plugins/dsh/skills/delphi-review/scripts/verify-consensus.sh +43 -0
- package/plugins/dsh/skills/delphi-review/tools.md +29 -0
- package/plugins/dsh/skills/domain-modeling/ADR-FORMAT.md +64 -0
- package/plugins/dsh/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/plugins/dsh/skills/domain-modeling/SKILL.md +74 -0
- package/plugins/dsh/skills/grill-with-docs/SKILL.md +7 -0
- package/plugins/dsh/skills/grilling/SKILL.md +12 -0
- package/plugins/dsh/skills/improve-codebase-architecture/SKILL.md +156 -0
- package/plugins/dsh/skills/ralph-loop/SKILL.md +198 -0
- package/plugins/dsh/skills/ralph-loop/references/components.md +113 -0
- package/plugins/dsh/skills/ralph-loop/references/phase-2-build-ralph.md +89 -0
- package/plugins/dsh/skills/ralph-loop/references/workflow-details.md +99 -0
- package/plugins/dsh/skills/ralph-loop/templates/progress-log.md +36 -0
- package/plugins/dsh/skills/sprint-flow/AGENTS.md +103 -0
- package/plugins/dsh/skills/sprint-flow/SKILL.md +411 -0
- package/plugins/dsh/skills/sprint-flow/__tests__/sprint-flow.test.cjs +457 -0
- package/plugins/dsh/skills/sprint-flow/hooks.md +18 -0
- package/plugins/dsh/skills/sprint-flow/references/components/memory.md +87 -0
- package/plugins/dsh/skills/sprint-flow/references/components/middleware.md +75 -0
- package/plugins/dsh/skills/sprint-flow/references/components/skill-invocations.md +105 -0
- package/plugins/dsh/skills/sprint-flow/references/components/system-prompt.md +27 -0
- package/plugins/dsh/skills/sprint-flow/references/components/tool-descriptions.md +95 -0
- package/plugins/dsh/skills/sprint-flow/references/force-levels.md +204 -0
- package/plugins/dsh/skills/sprint-flow/references/orchestration-rules.md +236 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-1-prep.md +294 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-2-design.md +273 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-3-build.md +348 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-4-verify.md +225 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-5-ship.md +222 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-6-close.md +266 -0
- package/plugins/dsh/skills/sprint-flow/references/phase-overview.md +486 -0
- package/plugins/dsh/skills/sprint-flow/scripts/verify-sprint-state.sh +38 -0
- package/plugins/dsh/skills/sprint-flow/templates/auto-estimate-learning-log.md +136 -0
- package/plugins/dsh/skills/sprint-flow/templates/auto-estimate-output-template.md +110 -0
- package/plugins/dsh/skills/sprint-flow/templates/emergent-issues-template.md +120 -0
- package/plugins/dsh/skills/sprint-flow/templates/pain-document-template.md +115 -0
- package/plugins/dsh/skills/sprint-flow/templates/sprint-progress-template.md +140 -0
- package/plugins/dsh/skills/sprint-flow/templates/sprint-summary-template.md +121 -0
- package/plugins/dsh/skills/sprint-flow/tools.md +29 -0
- package/plugins/dsh/skills/test-driven-development/SKILL.md +371 -0
- package/plugins/dsh/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +56 -0
- package/plugins/dsh/skills/test-specification-alignment/SKILL.md +205 -0
- package/plugins/dsh/skills/test-specification-alignment/references/alignment-verification-algorithm.md +493 -0
- package/plugins/dsh/skills/test-specification-alignment/references/phase2-constraint-enforcement.md +431 -0
- package/plugins/dsh/skills/test-specification-alignment/references/specification-format.md +348 -0
- package/plugins/dsh/skills/to-issues/SKILL.md +277 -0
- package/plugins/dsh/src/command.test.ts +102 -0
- package/plugins/dsh/src/command.ts +75 -0
- package/plugins/dsh/src/contract.test.ts +62 -0
- package/plugins/dsh/src/gate-runner.test.ts +100 -0
- package/plugins/dsh/src/gate-runner.ts +58 -0
- package/plugins/dsh/src/index.test.ts +97 -0
- package/plugins/dsh/src/index.ts +94 -0
- package/plugins/dsh/src/skills.test.ts +58 -0
- package/plugins/dsh/tsconfig.build.json +13 -0
- package/plugins/dsh/tsconfig.json +19 -0
- package/plugins/dsh/vitest.config.ts +8 -0
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/scripts/prepack.cjs +1 -0
- package/plugins/opencode/skills/clipboard-vision/SKILL.md +47 -0
- package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
- package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
- package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
- package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
- package/plugins/opencode/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
- package/plugins/opencode/skills/clipboard-vision/describe-clipboard.sh +161 -0
- package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
- package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
- package/plugins/opencode/skills/delphi-review/.delphi-config.json.example +24 -27
- package/plugins/opencode/skills/delphi-review/AGENTS.md +13 -12
- package/plugins/opencode/skills/delphi-review/INSTALL.md +15 -17
- package/plugins/opencode/skills/delphi-review/SKILL.md +30 -29
- package/plugins/opencode/skills/delphi-review/opencode.json.delphi.example +6 -10
- package/plugins/opencode/skills/delphi-review/references/code-walkthrough.md +33 -49
- package/plugins/opencode/skills/delphi-review/references/requirements.md +66 -54
- package/plugins/opencode/skills/delphi-review/references/round-templates.md +7 -7
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +5 -5
- package/plugins/opencode/skills/sprint-flow/SKILL.md +4 -4
- package/plugins/opencode/skills/sprint-flow/references/components/skill-invocations.md +2 -2
- package/plugins/opencode/skills/sprint-flow/references/force-levels.md +37 -35
- package/plugins/opencode/skills/sprint-flow/references/orchestration-rules.md +1 -1
- package/plugins/opencode/skills/sprint-flow/references/phase-1-prep.md +1 -1
- package/plugins/opencode/skills/sprint-flow/references/phase-2-design.md +24 -14
- package/plugins/opencode/skills/sprint-flow/references/phase-4-verify.md +6 -6
- package/plugins/opencode/skills/sprint-flow/references/phase-overview.md +2 -2
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +4 -4
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/clipboard-vision/SKILL.md +47 -0
- package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
- package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
- package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
- package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/SKILL.md +47 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
- package/plugins/qoder/skills/clipboard-vision/clipboard-vision/scripts/clipboard-vision.sh +137 -0
- package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
- package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
- package/plugins/qoder/skills/delphi-review/.delphi-config.json.example +3 -11
- package/plugins/qoder/skills/delphi-review/AGENTS.md +15 -17
- package/plugins/qoder/skills/delphi-review/INSTALL.md +12 -12
- package/plugins/qoder/skills/delphi-review/SKILL.md +58 -25
- package/plugins/qoder/skills/delphi-review/opencode.json.delphi.example +1 -1
- package/plugins/qoder/skills/delphi-review/references/code-walkthrough.md +33 -49
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +5 -5
- package/plugins/qoder/skills/sprint-flow/SKILL.md +2 -2
- package/plugins/qoder/skills/sprint-flow/references/force-levels.md +38 -35
- package/plugins/qoder/skills/sprint-flow/references/phase-1-prep.md +1 -1
- package/plugins/qoder/skills/sprint-flow/references/phase-2-design.md +48 -6
- package/plugins/qoder/skills/sprint-flow/references/phase-4-verify.md +5 -6
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +4 -4
- package/principles/AGENTS.md +4 -4
- package/scripts/__tests__/sync-package-content.test.js +30 -0
- package/scripts/delphi-external-review.cjs +194 -63
- package/scripts/sync-package-content.js +9 -2
- package/skills/clipboard-vision/SKILL.md +47 -0
- package/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
- package/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
- package/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
- package/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
- package/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
- package/skills/clipboard-vision/describe-clipboard.sh +161 -0
- package/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
- package/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
- package/skills/delphi-review/.delphi-config.json.example +24 -27
- package/skills/delphi-review/AGENTS.md +13 -12
- package/skills/delphi-review/INSTALL.md +15 -17
- package/skills/delphi-review/SKILL.md +30 -29
- package/skills/delphi-review/opencode.json.delphi.example +6 -10
- package/skills/delphi-review/references/code-walkthrough.md +33 -49
- package/skills/delphi-review/references/requirements.md +66 -54
- package/skills/delphi-review/references/round-templates.md +7 -7
- package/skills/sprint-flow/AGENTS.md +5 -5
- package/skills/sprint-flow/SKILL.md +4 -4
- package/skills/sprint-flow/references/components/skill-invocations.md +2 -2
- package/skills/sprint-flow/references/force-levels.md +37 -35
- package/skills/sprint-flow/references/orchestration-rules.md +1 -1
- package/skills/sprint-flow/references/phase-1-prep.md +1 -1
- package/skills/sprint-flow/references/phase-2-design.md +24 -14
- package/skills/sprint-flow/references/phase-4-verify.md +6 -6
- package/skills/sprint-flow/references/phase-overview.md +2 -2
- package/skills/test-specification-alignment/AGENTS.md +4 -4
- 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
|
-
"
|
|
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":
|
|
33
|
+
"threshold_percent": 90,
|
|
42
34
|
"max_review_rounds": 5,
|
|
43
|
-
"
|
|
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-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 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
|
|
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:
|
|
29
|
-
| Config example | .delphi-config.json.example | 3 experts,
|
|
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
|
-
-
|
|
37
|
-
- Model selection: reads
|
|
38
|
-
-
|
|
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
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
>
|
|
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": "
|
|
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` | ✅ |
|
|
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
|
-
###
|
|
93
|
+
### Single-provider setup
|
|
94
94
|
|
|
95
|
-
|
|
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": "
|
|
108
|
-
"feasibility": { "provider": "
|
|
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
|
-
>
|
|
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.
|
|
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
|
-
### "
|
|
145
|
+
### "Expert model IDs are not distinct"
|
|
146
146
|
|
|
147
|
-
Configure
|
|
147
|
+
Configure three distinct callable model IDs. They may use the same provider.
|
|
148
148
|
|
|
149
149
|
### "Node.js >= 18 required"
|
|
150
150
|
|