@boyingliu01/xp-gate 0.20.2 → 0.21.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/adapters/python.sh +73 -6
- package/gate-10.sh +107 -64
- package/hooks/gate-10.sh +107 -64
- package/hooks/pre-commit +44 -21
- package/lib/mattpocock-license-verdict.json +1 -1
- package/mock-policy/AGENTS.md +4 -4
- package/mutation/AGENTS.md +4 -4
- package/package.json +1 -1
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +4 -4
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +4 -4
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +4 -4
- package/plugins/dsh/package.json +1 -1
- package/plugins/dsh/skills/delphi-review/AGENTS.md +4 -4
- package/plugins/dsh/skills/sprint-flow/AGENTS.md +4 -4
- package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +4 -4
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/skills/delphi-review/AGENTS.md +4 -4
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +4 -4
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +4 -4
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +4 -4
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +4 -4
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +4 -4
- package/principles/AGENTS.md +4 -4
- package/skills/delphi-review/AGENTS.md +4 -4
- package/skills/sprint-flow/AGENTS.md +4 -4
- package/skills/test-specification-alignment/AGENTS.md +4 -4
package/adapters/python.sh
CHANGED
|
@@ -9,10 +9,26 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
9
9
|
# shellcheck source=/dev/null
|
|
10
10
|
source "$SCRIPT_DIR/../adapter-common.sh" 2>/dev/null || true
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
# A mypy target must exist AND actually contain .py files: a bare directory
|
|
13
|
+
# check lets through TS repos' src/ (mypy exits 2 with "There are no .py[i]
|
|
14
|
+
# files in directory" — #513 R1 expert-B reproduction), and a file check
|
|
15
|
+
# alone would accept empty shell directories. Supports files too, so a
|
|
16
|
+
# scope declaration may name a single .py file.
|
|
17
|
+
_mypy_target_usable() {
|
|
18
|
+
[ -e "$1" ] || return 1
|
|
19
|
+
[ -n "$(find "$1" -name '*.py' -print 2>/dev/null | grep .)" ]
|
|
20
|
+
}
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
run_static_analysis() {
|
|
23
|
+
# NOTE: require_tool mypy runs AFTER target resolution, not here (#513 R2
|
|
24
|
+
# expert-C): a repo with no type surface AND no mypy installed must reach
|
|
25
|
+
# the SKIP branch (nothing to check) instead of false-BLOCKing on the
|
|
26
|
+
# missing tool. The tool is only required when there is something to check.
|
|
27
|
+
|
|
28
|
+
# 口径 = CI type job(.github/workflows/ci.yml:43-45)的目录集合(src/、
|
|
29
|
+
# scripts/),并按调用方式对齐:**逐目录单独调用**(#513 R1 专家 B 实测:
|
|
30
|
+
# 合并为 `mypy src scripts` 一次跑,src/util.py 与 scripts/util.py 同名时
|
|
31
|
+
# 报 "Duplicate module named" exit 2,而 CI 分开跑各自 exit 0)。
|
|
16
32
|
# 为什么不能写 `mypy .`:`.` 会递归扫到两类文件,而它们在仓库里从未被声明为
|
|
17
33
|
# 门禁面,CI 也从不检查:
|
|
18
34
|
# ① 根目录一次性调研/演示脚本(fetch_*.py、demo_*.py、validate_*.py 等)——
|
|
@@ -28,10 +44,61 @@ run_static_analysis() {
|
|
|
28
44
|
# 口径一致性由仓库侧 BATS 测试双向锁住:
|
|
29
45
|
# githooks/__tests__/adapter-mypy-pester-scope.test.bats(含"适配器里不得再
|
|
30
46
|
# 出现裸 mypy ."),防止 `mypy .` 被写回来时无人报警。
|
|
47
|
+
#
|
|
48
|
+
# #513:上述 `src/`+`scripts/` 是"单一仓库的 CI 声明面",不能当成所有 Python
|
|
49
|
+
# 仓库的布局硬编码——无 src/ 的仓库(如 skill-cert 的 engine/ 布局)会得到
|
|
50
|
+
# `mypy: can't read file 'src'` 而对任何 .py 提交恒 BLOCK,违反本项目
|
|
51
|
+
# "门禁无法运行 → SKIP 而非 BLOCK" 规范。口径回归"按仓库声明"三级解析:
|
|
52
|
+
# ① 仓库根 `.xp-gate-mypy-scope`(每行一个目录;支持整行或行内 # 注释)
|
|
53
|
+
# 存在则为其权威声明,声明条目同样过 usable 守卫(缺失/无 .py → WARN 跳过);
|
|
54
|
+
# ② 否则仅对 usable 的默认目录(src/、scripts/)执行;
|
|
55
|
+
# ③ 两者皆无(或声明为空)→ 打印提示并 exit 0,绝不把 mypy 空跑一次。
|
|
31
56
|
echo "Running Python static analysis (mypy)..."
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
57
|
+
local -a MYPY_TARGETS=()
|
|
58
|
+
local _mypy_declared=0
|
|
59
|
+
if [ -f .xp-gate-mypy-scope ]; then
|
|
60
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
61
|
+
line="${line%%#*}"
|
|
62
|
+
line="${line#"${line%%[![:space:]]*}"}"
|
|
63
|
+
line="${line%"${line##*[![:space:]]}"}"
|
|
64
|
+
[ -z "$line" ] && continue
|
|
65
|
+
_mypy_declared=1
|
|
66
|
+
if _mypy_target_usable "$line"; then
|
|
67
|
+
MYPY_TARGETS+=("$line")
|
|
68
|
+
else
|
|
69
|
+
echo " ⚠ mypy scope: declared target '$line' does not exist or contains no .py files — skipped"
|
|
70
|
+
fi
|
|
71
|
+
done < .xp-gate-mypy-scope
|
|
72
|
+
echo " scope: .xp-gate-mypy-scope declaration"
|
|
73
|
+
if [ "${#MYPY_TARGETS[@]}" -eq 0 ]; then
|
|
74
|
+
if [ "$_mypy_declared" -eq 1 ]; then
|
|
75
|
+
echo " ⚠ mypy: .xp-gate-mypy-scope has no usable target (all missing or without .py files) — skipping"
|
|
76
|
+
else
|
|
77
|
+
echo " ⚠ mypy: .xp-gate-mypy-scope is present but empty (comments/blank lines only) — skipping"
|
|
78
|
+
fi
|
|
79
|
+
return 0
|
|
80
|
+
fi
|
|
81
|
+
else
|
|
82
|
+
if [ -d src ] && _mypy_target_usable src; then
|
|
83
|
+
MYPY_TARGETS+=(src)
|
|
84
|
+
fi
|
|
85
|
+
if [ -d scripts ] && _mypy_target_usable scripts; then
|
|
86
|
+
MYPY_TARGETS+=(scripts)
|
|
87
|
+
fi
|
|
88
|
+
if [ "${#MYPY_TARGETS[@]}" -eq 0 ]; then
|
|
89
|
+
echo " ℹ️ mypy: repo declares no type surface (no .xp-gate-mypy-scope; src/ scripts/ absent or without .py files) — skipping"
|
|
90
|
+
echo " if this repo does have a type surface, declare it: create .xp-gate-mypy-scope (one directory per line)"
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
# 逐目标调用并聚合退出码(口径见函数头注释)。
|
|
95
|
+
require_tool mypy "mypy" || return 1
|
|
96
|
+
local _mypy_rc=0
|
|
97
|
+
local _mypy_t
|
|
98
|
+
for _mypy_t in "${MYPY_TARGETS[@]}"; do
|
|
99
|
+
mypy "$_mypy_t" || _mypy_rc=1
|
|
100
|
+
done
|
|
101
|
+
return $_mypy_rc
|
|
35
102
|
}
|
|
36
103
|
|
|
37
104
|
run_lint() {
|
package/gate-10.sh
CHANGED
|
@@ -57,82 +57,125 @@ else
|
|
|
57
57
|
$SEMGREP_FILES
|
|
58
58
|
EOF
|
|
59
59
|
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
# The verdict is parsed from the JSON with node (see below), so node is a
|
|
61
|
+
# hard dependency of this gate — check it BEFORE spending a semgrep run
|
|
62
|
+
# (#518 R2): without it we would silently SKIP every finding as
|
|
63
|
+
# "unparseable" and lose the whole security net on minimal CI images.
|
|
64
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
65
|
+
echo " ⚠️ WARN - node is not installed — Gate 10 needs it to parse semgrep's JSON verdict"
|
|
66
|
+
echo " Install node (https://nodejs.org); without it SAST findings cannot be classified"
|
|
67
|
+
echo " ⏭️ SKIPPED - SAST (node not installed)"
|
|
68
|
+
GATE_10_STATUS="SKIP"
|
|
69
|
+
else
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
# Run semgrep with JSON output. stdout and stderr are captured SEPARATELY:
|
|
72
|
+
# --json writes findings to stdout, progress/summary lines to stderr, and the
|
|
73
|
+
# old `2>&1` merge poisoned the very JSON the verdict now depends on (#518).
|
|
74
|
+
# SEMGREP_OUTPUT keeps its name and role — what the tool said, printed on the
|
|
75
|
+
# SKIP path (AC-475-04).
|
|
76
|
+
#
|
|
77
|
+
# #518: the exit code does NOT carry the verdict. semgrep exits 0 even with
|
|
78
|
+
# ERROR-severity findings, and its exit-code semantics have drifted across
|
|
79
|
+
# versions and platforms (upstream currently reports findings WITH --error
|
|
80
|
+
# as exit 1 and failures as 2, but that mapping is not something a gate
|
|
81
|
+
# should bet on). The JSON carries what the exit code never could —
|
|
82
|
+
# per-severity counts — so the verdict is read from the JSON and the exit
|
|
83
|
+
# code is demoted to "did the tool itself run". --error stays OFF: it would
|
|
84
|
+
# add nothing the JSON does not already provide, and keeping it off leaves
|
|
85
|
+
# failure exit codes unambiguous for the #475 diagnostics path.
|
|
86
|
+
SEMGREP_STDOUT_FILE=$(mktemp)
|
|
87
|
+
SEMGREP_OUTPUT=$("$SEMGREP_CMD" scan --config=p/security-audit --json --disable-version-check "${SEMGREP_ARGS[@]}" 2>&1 >"$SEMGREP_STDOUT_FILE")
|
|
88
|
+
SEMGREP_EXIT=$?
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
# One node pass over the JSON: first line = verdict counts, remaining lines =
|
|
91
|
+
# finding details. The severity vocabulary is the UNION of the two scales
|
|
92
|
+
# (#518): semgrep's own ERROR is its most severe tier (it maps to the old
|
|
93
|
+
# CRITICAL/HIGH → BLOCK intent), its WARNING/INFO align with the old
|
|
94
|
+
# MEDIUM/LOW → warnings-only tier. Anything OUTSIDE both lists (missing,
|
|
95
|
+
# empty, or a future/new tier) counts as BLOCKING — a security gate must
|
|
96
|
+
# fail closed on severities it does not recognize (#518 R2). Parsing
|
|
97
|
+
# failure degrades to PARSE=FAIL — a fail-closed SKIP below, never a PASS.
|
|
98
|
+
SEMGREP_VERDICT=$(node -e '
|
|
99
|
+
let d="";process.stdin.on("data",c=>d+=c);process.stdin.on("end",()=>{
|
|
100
|
+
let data;try{data=JSON.parse(d);}catch(e){console.log("PARSE=FAIL RESULTS=0 ERRORS=0 BLOCKING=0 WARNINGS=0");return;}
|
|
101
|
+
const results=data.results||[];const errors=data.errors||[];
|
|
102
|
+
const sev=r=>((r.extra&&r.extra.severity)||"").toUpperCase();
|
|
103
|
+
const WARNV=["WARNING","INFO","MEDIUM","LOW"];
|
|
104
|
+
let b=0,w=0;results.forEach(r=>{if(WARNV.indexOf(sev(r))>=0)w++;else b++;});
|
|
105
|
+
console.log("PARSE=OK RESULTS="+results.length+" ERRORS="+errors.length+" BLOCKING="+b+" WARNINGS="+w);
|
|
106
|
+
results.slice(0,5).forEach(r=>{const extra=r.extra||{};const s=sev(r)||"UNKNOWN";
|
|
107
|
+
console.log(" ["+s+"] "+(r.check_id||"unknown"));
|
|
108
|
+
console.log(" "+(r.path||"unknown")+":"+((r.start&&r.start.line)||"?")+" → "+(extra.message||"").slice(0,80));
|
|
109
|
+
console.log("");});
|
|
110
|
+
});' < "$SEMGREP_STDOUT_FILE") || SEMGREP_VERDICT="PARSE=FAIL RESULTS=0 ERRORS=0 BLOCKING=0 WARNINGS=0"
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
112
|
+
PARSE_LINE=$(printf '%s\n' "$SEMGREP_VERDICT" | sed -n '1p')
|
|
113
|
+
FINDING_DETAILS=$(printf '%s\n' "$SEMGREP_VERDICT" | sed -n '2,$p')
|
|
114
|
+
V_PARSE=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/^PARSE=\([A-Z]*\) .*/\1/p')
|
|
115
|
+
V_RESULTS=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* RESULTS=\([0-9]*\) .*/\1/p')
|
|
116
|
+
V_ERRORS=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* ERRORS=\([0-9]*\) .*/\1/p')
|
|
117
|
+
V_BLOCKING=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* BLOCKING=\([0-9]*\) .*/\1/p')
|
|
118
|
+
V_WARNINGS=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* WARNINGS=\([0-9]*\)$/\1/p')
|
|
119
|
+
# Keep the raw stdout tail for the unparseable branch's diagnostics BEFORE
|
|
120
|
+
# the temp file goes away (#518 R2: stderr alone often says nothing there).
|
|
121
|
+
SEMGREP_STDOUT_TAIL=$(tail -5 "$SEMGREP_STDOUT_FILE" 2>/dev/null)
|
|
122
|
+
rm -f "$SEMGREP_STDOUT_FILE"
|
|
97
123
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
echo "
|
|
107
|
-
|
|
108
|
-
echo "$FINDING_DETAILS"
|
|
109
|
-
echo " Run 'semgrep scan --config=p/security-audit' to review all findings."
|
|
110
|
-
GATE_10_STATUS="FAIL"
|
|
111
|
-
exit 1
|
|
112
|
-
else
|
|
113
|
-
echo ""
|
|
114
|
-
echo " ✅ PASSED - No critical/high vulnerabilities"
|
|
115
|
-
if [ "$MEDIUM_LOW" -gt 0 ]; then
|
|
116
|
-
echo " ⚠️ ${MEDIUM_LOW} medium/low findings (warnings only)"
|
|
117
|
-
echo "$FINDING_DETAILS"
|
|
118
|
-
fi
|
|
119
|
-
GATE_10_STATUS="PASS"
|
|
124
|
+
# Fail closed: an unparseable payload OR an OK parse with any missing count
|
|
125
|
+
# field (verdict-line format drift) must SKIP, never silently degrade to
|
|
126
|
+
# PASS (#518).
|
|
127
|
+
if [ "$V_PARSE" != "OK" ] || [ -z "$V_RESULTS" ] || [ -z "$V_ERRORS" ] || [ -z "$V_BLOCKING" ] || [ -z "$V_WARNINGS" ]; then
|
|
128
|
+
# Unparseable output: nothing the exit code claims can be trusted (#518).
|
|
129
|
+
# Fail closed — SKIP with diagnostics, never a PASS.
|
|
130
|
+
echo " ⚠️ semgrep output unparseable or verdict fields missing (exit code ${SEMGREP_EXIT}) — cannot determine verdict"
|
|
131
|
+
if [ -n "$SEMGREP_OUTPUT" ]; then
|
|
132
|
+
echo " ── what semgrep reported on stderr ──"
|
|
133
|
+
printf '%s\n' "$SEMGREP_OUTPUT" | tail -10 | sed 's/^/ /'
|
|
120
134
|
fi
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
if [ -n "$SEMGREP_STDOUT_TAIL" ]; then
|
|
136
|
+
echo " ── what semgrep wrote to stdout (tail) ──"
|
|
137
|
+
printf '%s\n' "$SEMGREP_STDOUT_TAIL" | sed 's/^/ /'
|
|
138
|
+
fi
|
|
139
|
+
echo " ⏭️ SKIPPED - SAST (semgrep output unparseable)"
|
|
140
|
+
GATE_10_STATUS="SKIP"
|
|
141
|
+
elif [ "$V_RESULTS" -eq 0 ] && { [ "$V_ERRORS" -gt 0 ] || [ "$SEMGREP_EXIT" -ne 0 ]; }; then
|
|
142
|
+
# Nothing was scanned to a verdict: semgrep either failed outright
|
|
143
|
+
# (nonzero exit) or completed but reported scan errors for every input
|
|
144
|
+
# (#518 R2: exit 0 + results:[] + errors:[{...}] used to fall through to
|
|
145
|
+
# PASS). An operational failure must neither block nor claim a pass
|
|
146
|
+
# (#475 kept).
|
|
147
|
+
echo " ⚠️ semgrep exit=${SEMGREP_EXIT}, scan errors=${V_ERRORS}, findings=${V_RESULTS} — nothing to judge"
|
|
129
148
|
if [ -n "$SEMGREP_OUTPUT" ]; then
|
|
130
149
|
echo " ── what semgrep reported ──"
|
|
131
150
|
printf '%s\n' "$SEMGREP_OUTPUT" | tail -10 | sed 's/^/ /'
|
|
132
151
|
fi
|
|
133
152
|
echo " ⏭️ SKIPPED - SAST (semgrep runtime error)"
|
|
134
153
|
GATE_10_STATUS="SKIP"
|
|
154
|
+
elif [ "$V_BLOCKING" -gt 0 ]; then
|
|
155
|
+
echo ""
|
|
156
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
157
|
+
echo " GATE 10: Semgrep Security Gate"
|
|
158
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
159
|
+
echo " CRITICAL/HIGH/ERROR: ${V_BLOCKING} ❌ BLOCKED"
|
|
160
|
+
echo " MEDIUM/LOW/WARNING/INFO: ${V_WARNINGS} ⚠️ warning"
|
|
161
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
162
|
+
echo " ❌ BLOCKED — blocking-severity vulnerability found"
|
|
163
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
164
|
+
echo "$FINDING_DETAILS"
|
|
165
|
+
echo " Run 'semgrep scan --config=p/security-audit' to review all findings."
|
|
166
|
+
GATE_10_STATUS="FAIL"
|
|
167
|
+
exit 1
|
|
168
|
+
else
|
|
169
|
+
echo ""
|
|
170
|
+
echo " ✅ PASSED - No blocking vulnerabilities (files scanned: ${#SEMGREP_ARGS[@]})"
|
|
171
|
+
if [ "$V_WARNINGS" -gt 0 ]; then
|
|
172
|
+
echo " ⚠️ ${V_WARNINGS} non-blocking findings (warnings only)"
|
|
173
|
+
echo "$FINDING_DETAILS"
|
|
174
|
+
fi
|
|
175
|
+
GATE_10_STATUS="PASS"
|
|
135
176
|
fi
|
|
177
|
+
|
|
178
|
+
fi # node available
|
|
136
179
|
fi
|
|
137
180
|
fi
|
|
138
181
|
record_gate_audit "gate-10" "sast-security" "$GATE_10_STATUS" "0" "$GATE_10_START"
|
package/hooks/gate-10.sh
CHANGED
|
@@ -57,82 +57,125 @@ else
|
|
|
57
57
|
$SEMGREP_FILES
|
|
58
58
|
EOF
|
|
59
59
|
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
# The verdict is parsed from the JSON with node (see below), so node is a
|
|
61
|
+
# hard dependency of this gate — check it BEFORE spending a semgrep run
|
|
62
|
+
# (#518 R2): without it we would silently SKIP every finding as
|
|
63
|
+
# "unparseable" and lose the whole security net on minimal CI images.
|
|
64
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
65
|
+
echo " ⚠️ WARN - node is not installed — Gate 10 needs it to parse semgrep's JSON verdict"
|
|
66
|
+
echo " Install node (https://nodejs.org); without it SAST findings cannot be classified"
|
|
67
|
+
echo " ⏭️ SKIPPED - SAST (node not installed)"
|
|
68
|
+
GATE_10_STATUS="SKIP"
|
|
69
|
+
else
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
# Run semgrep with JSON output. stdout and stderr are captured SEPARATELY:
|
|
72
|
+
# --json writes findings to stdout, progress/summary lines to stderr, and the
|
|
73
|
+
# old `2>&1` merge poisoned the very JSON the verdict now depends on (#518).
|
|
74
|
+
# SEMGREP_OUTPUT keeps its name and role — what the tool said, printed on the
|
|
75
|
+
# SKIP path (AC-475-04).
|
|
76
|
+
#
|
|
77
|
+
# #518: the exit code does NOT carry the verdict. semgrep exits 0 even with
|
|
78
|
+
# ERROR-severity findings, and its exit-code semantics have drifted across
|
|
79
|
+
# versions and platforms (upstream currently reports findings WITH --error
|
|
80
|
+
# as exit 1 and failures as 2, but that mapping is not something a gate
|
|
81
|
+
# should bet on). The JSON carries what the exit code never could —
|
|
82
|
+
# per-severity counts — so the verdict is read from the JSON and the exit
|
|
83
|
+
# code is demoted to "did the tool itself run". --error stays OFF: it would
|
|
84
|
+
# add nothing the JSON does not already provide, and keeping it off leaves
|
|
85
|
+
# failure exit codes unambiguous for the #475 diagnostics path.
|
|
86
|
+
SEMGREP_STDOUT_FILE=$(mktemp)
|
|
87
|
+
SEMGREP_OUTPUT=$("$SEMGREP_CMD" scan --config=p/security-audit --json --disable-version-check "${SEMGREP_ARGS[@]}" 2>&1 >"$SEMGREP_STDOUT_FILE")
|
|
88
|
+
SEMGREP_EXIT=$?
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
# One node pass over the JSON: first line = verdict counts, remaining lines =
|
|
91
|
+
# finding details. The severity vocabulary is the UNION of the two scales
|
|
92
|
+
# (#518): semgrep's own ERROR is its most severe tier (it maps to the old
|
|
93
|
+
# CRITICAL/HIGH → BLOCK intent), its WARNING/INFO align with the old
|
|
94
|
+
# MEDIUM/LOW → warnings-only tier. Anything OUTSIDE both lists (missing,
|
|
95
|
+
# empty, or a future/new tier) counts as BLOCKING — a security gate must
|
|
96
|
+
# fail closed on severities it does not recognize (#518 R2). Parsing
|
|
97
|
+
# failure degrades to PARSE=FAIL — a fail-closed SKIP below, never a PASS.
|
|
98
|
+
SEMGREP_VERDICT=$(node -e '
|
|
99
|
+
let d="";process.stdin.on("data",c=>d+=c);process.stdin.on("end",()=>{
|
|
100
|
+
let data;try{data=JSON.parse(d);}catch(e){console.log("PARSE=FAIL RESULTS=0 ERRORS=0 BLOCKING=0 WARNINGS=0");return;}
|
|
101
|
+
const results=data.results||[];const errors=data.errors||[];
|
|
102
|
+
const sev=r=>((r.extra&&r.extra.severity)||"").toUpperCase();
|
|
103
|
+
const WARNV=["WARNING","INFO","MEDIUM","LOW"];
|
|
104
|
+
let b=0,w=0;results.forEach(r=>{if(WARNV.indexOf(sev(r))>=0)w++;else b++;});
|
|
105
|
+
console.log("PARSE=OK RESULTS="+results.length+" ERRORS="+errors.length+" BLOCKING="+b+" WARNINGS="+w);
|
|
106
|
+
results.slice(0,5).forEach(r=>{const extra=r.extra||{};const s=sev(r)||"UNKNOWN";
|
|
107
|
+
console.log(" ["+s+"] "+(r.check_id||"unknown"));
|
|
108
|
+
console.log(" "+(r.path||"unknown")+":"+((r.start&&r.start.line)||"?")+" → "+(extra.message||"").slice(0,80));
|
|
109
|
+
console.log("");});
|
|
110
|
+
});' < "$SEMGREP_STDOUT_FILE") || SEMGREP_VERDICT="PARSE=FAIL RESULTS=0 ERRORS=0 BLOCKING=0 WARNINGS=0"
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
112
|
+
PARSE_LINE=$(printf '%s\n' "$SEMGREP_VERDICT" | sed -n '1p')
|
|
113
|
+
FINDING_DETAILS=$(printf '%s\n' "$SEMGREP_VERDICT" | sed -n '2,$p')
|
|
114
|
+
V_PARSE=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/^PARSE=\([A-Z]*\) .*/\1/p')
|
|
115
|
+
V_RESULTS=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* RESULTS=\([0-9]*\) .*/\1/p')
|
|
116
|
+
V_ERRORS=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* ERRORS=\([0-9]*\) .*/\1/p')
|
|
117
|
+
V_BLOCKING=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* BLOCKING=\([0-9]*\) .*/\1/p')
|
|
118
|
+
V_WARNINGS=$(printf '%s\n' "$PARSE_LINE" | sed -n 's/.* WARNINGS=\([0-9]*\)$/\1/p')
|
|
119
|
+
# Keep the raw stdout tail for the unparseable branch's diagnostics BEFORE
|
|
120
|
+
# the temp file goes away (#518 R2: stderr alone often says nothing there).
|
|
121
|
+
SEMGREP_STDOUT_TAIL=$(tail -5 "$SEMGREP_STDOUT_FILE" 2>/dev/null)
|
|
122
|
+
rm -f "$SEMGREP_STDOUT_FILE"
|
|
97
123
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
echo "
|
|
107
|
-
|
|
108
|
-
echo "$FINDING_DETAILS"
|
|
109
|
-
echo " Run 'semgrep scan --config=p/security-audit' to review all findings."
|
|
110
|
-
GATE_10_STATUS="FAIL"
|
|
111
|
-
exit 1
|
|
112
|
-
else
|
|
113
|
-
echo ""
|
|
114
|
-
echo " ✅ PASSED - No critical/high vulnerabilities"
|
|
115
|
-
if [ "$MEDIUM_LOW" -gt 0 ]; then
|
|
116
|
-
echo " ⚠️ ${MEDIUM_LOW} medium/low findings (warnings only)"
|
|
117
|
-
echo "$FINDING_DETAILS"
|
|
118
|
-
fi
|
|
119
|
-
GATE_10_STATUS="PASS"
|
|
124
|
+
# Fail closed: an unparseable payload OR an OK parse with any missing count
|
|
125
|
+
# field (verdict-line format drift) must SKIP, never silently degrade to
|
|
126
|
+
# PASS (#518).
|
|
127
|
+
if [ "$V_PARSE" != "OK" ] || [ -z "$V_RESULTS" ] || [ -z "$V_ERRORS" ] || [ -z "$V_BLOCKING" ] || [ -z "$V_WARNINGS" ]; then
|
|
128
|
+
# Unparseable output: nothing the exit code claims can be trusted (#518).
|
|
129
|
+
# Fail closed — SKIP with diagnostics, never a PASS.
|
|
130
|
+
echo " ⚠️ semgrep output unparseable or verdict fields missing (exit code ${SEMGREP_EXIT}) — cannot determine verdict"
|
|
131
|
+
if [ -n "$SEMGREP_OUTPUT" ]; then
|
|
132
|
+
echo " ── what semgrep reported on stderr ──"
|
|
133
|
+
printf '%s\n' "$SEMGREP_OUTPUT" | tail -10 | sed 's/^/ /'
|
|
120
134
|
fi
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
if [ -n "$SEMGREP_STDOUT_TAIL" ]; then
|
|
136
|
+
echo " ── what semgrep wrote to stdout (tail) ──"
|
|
137
|
+
printf '%s\n' "$SEMGREP_STDOUT_TAIL" | sed 's/^/ /'
|
|
138
|
+
fi
|
|
139
|
+
echo " ⏭️ SKIPPED - SAST (semgrep output unparseable)"
|
|
140
|
+
GATE_10_STATUS="SKIP"
|
|
141
|
+
elif [ "$V_RESULTS" -eq 0 ] && { [ "$V_ERRORS" -gt 0 ] || [ "$SEMGREP_EXIT" -ne 0 ]; }; then
|
|
142
|
+
# Nothing was scanned to a verdict: semgrep either failed outright
|
|
143
|
+
# (nonzero exit) or completed but reported scan errors for every input
|
|
144
|
+
# (#518 R2: exit 0 + results:[] + errors:[{...}] used to fall through to
|
|
145
|
+
# PASS). An operational failure must neither block nor claim a pass
|
|
146
|
+
# (#475 kept).
|
|
147
|
+
echo " ⚠️ semgrep exit=${SEMGREP_EXIT}, scan errors=${V_ERRORS}, findings=${V_RESULTS} — nothing to judge"
|
|
129
148
|
if [ -n "$SEMGREP_OUTPUT" ]; then
|
|
130
149
|
echo " ── what semgrep reported ──"
|
|
131
150
|
printf '%s\n' "$SEMGREP_OUTPUT" | tail -10 | sed 's/^/ /'
|
|
132
151
|
fi
|
|
133
152
|
echo " ⏭️ SKIPPED - SAST (semgrep runtime error)"
|
|
134
153
|
GATE_10_STATUS="SKIP"
|
|
154
|
+
elif [ "$V_BLOCKING" -gt 0 ]; then
|
|
155
|
+
echo ""
|
|
156
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
157
|
+
echo " GATE 10: Semgrep Security Gate"
|
|
158
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
159
|
+
echo " CRITICAL/HIGH/ERROR: ${V_BLOCKING} ❌ BLOCKED"
|
|
160
|
+
echo " MEDIUM/LOW/WARNING/INFO: ${V_WARNINGS} ⚠️ warning"
|
|
161
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
162
|
+
echo " ❌ BLOCKED — blocking-severity vulnerability found"
|
|
163
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
164
|
+
echo "$FINDING_DETAILS"
|
|
165
|
+
echo " Run 'semgrep scan --config=p/security-audit' to review all findings."
|
|
166
|
+
GATE_10_STATUS="FAIL"
|
|
167
|
+
exit 1
|
|
168
|
+
else
|
|
169
|
+
echo ""
|
|
170
|
+
echo " ✅ PASSED - No blocking vulnerabilities (files scanned: ${#SEMGREP_ARGS[@]})"
|
|
171
|
+
if [ "$V_WARNINGS" -gt 0 ]; then
|
|
172
|
+
echo " ⚠️ ${V_WARNINGS} non-blocking findings (warnings only)"
|
|
173
|
+
echo "$FINDING_DETAILS"
|
|
174
|
+
fi
|
|
175
|
+
GATE_10_STATUS="PASS"
|
|
135
176
|
fi
|
|
177
|
+
|
|
178
|
+
fi # node available
|
|
136
179
|
fi
|
|
137
180
|
fi
|
|
138
181
|
record_gate_audit "gate-10" "sast-security" "$GATE_10_STATUS" "0" "$GATE_10_START"
|
package/hooks/pre-commit
CHANGED
|
@@ -710,30 +710,53 @@ if [ -z "$PROJECT_LANGS" ] && [ -z "$_CONFIG_LANGS" ]; then
|
|
|
710
710
|
done
|
|
711
711
|
return 1
|
|
712
712
|
}
|
|
713
|
+
# #515: when the repo ROOT itself declares the project, a nested marker that
|
|
714
|
+
# is merely a module file (skill_cert/cli/setup.py incident) must not hijack
|
|
715
|
+
# PROJECT_SUBDIR — Gates 1-9 would run from the wrong cwd and false-BLOCK on
|
|
716
|
+
# root-relative paths. The root-marker set below MUST stay aligned with
|
|
717
|
+
# _detect_subdir's marker set above (10 markers): every ecosystem recognized
|
|
718
|
+
# for subproject derivation is also protected at the root. The JS-monorepo
|
|
719
|
+
# check runs FIRST (#515 R2 delphi walkthrough): a root package.json with a
|
|
720
|
+
# "workspaces" key declares a JS monorepo (often together with a shared
|
|
721
|
+
# tsconfig.json), not a single project, so derivation keeps running there.
|
|
722
|
+
# Known limitation (#527): Gradle multi-module, CMake subdirectories and
|
|
723
|
+
# pnpm/Lerna workspaces are not disambiguated from single projects yet —
|
|
724
|
+
# see the pinned BATS case.
|
|
725
|
+
_skip_subdir_derive=0
|
|
726
|
+
if [ -f package.json ] && grep -q '"workspaces":' package.json 2>/dev/null; then
|
|
727
|
+
_skip_subdir_derive=0 # JS monorepo root: subproject derivation stays on
|
|
728
|
+
elif [ -f package.json ] || [ -f tsconfig.json ] || [ -f pyproject.toml ] || \
|
|
729
|
+
[ -f setup.py ] || [ -f go.mod ] || [ -f pubspec.yaml ] || \
|
|
730
|
+
[ -f pom.xml ] || [ -f build.gradle ] || \
|
|
731
|
+
[ -f build.gradle.kts ] || [ -f CMakeLists.txt ]; then
|
|
732
|
+
_skip_subdir_derive=1
|
|
733
|
+
fi
|
|
713
734
|
_subdir_set=""
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
735
|
+
if [ "$_skip_subdir_derive" -eq 0 ]; then
|
|
736
|
+
while IFS= read -r _changed; do
|
|
737
|
+
[ -z "$_changed" ] && continue
|
|
738
|
+
_d=$(_detect_subdir "$_changed" 2>/dev/null) || true
|
|
739
|
+
if [ -n "$_d" ] && [ "$_d" != "." ]; then
|
|
740
|
+
case " $_subdir_set " in
|
|
741
|
+
*" $_d "*) ;; # already seen
|
|
742
|
+
*) _subdir_set="${_subdir_set} $_d" ;;
|
|
743
|
+
esac
|
|
744
|
+
fi
|
|
745
|
+
done <<CHANGEDFILELIST
|
|
724
746
|
$CHANGED_FILES
|
|
725
747
|
CHANGEDFILELIST
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
748
|
+
_subdir_count=$(echo "$_subdir_set" | awk '{ n=0; for(i=1;i<=NF;i++) n++; print n }')
|
|
749
|
+
if [ "$_subdir_count" = "1" ]; then
|
|
750
|
+
PROJECT_SUBDIR=$(echo "$_subdir_set" | awk '{print $1}')
|
|
751
|
+
echo ""
|
|
752
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
753
|
+
echo " 📁 MULTILANGUAGE SUBDIR DETECTED FROM CHANGED FILES"
|
|
754
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
755
|
+
echo ""
|
|
756
|
+
echo "Language: $PROJECT_LANGS"
|
|
757
|
+
echo "Location: $PROJECT_SUBDIR/"
|
|
758
|
+
echo ""
|
|
759
|
+
fi
|
|
737
760
|
fi
|
|
738
761
|
fi
|
|
739
762
|
|
package/mock-policy/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MOCK-POLICY KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Mock layering policy enforcement — Gate M3 of pre-push hook. Ensures integration tests use real implementations for internal dependencies, mock external dependencies, and annotate pending mocks with removal plans. Combines project scope scanning, mock decision engine, and per-file validation into a single pipeline.
|
package/mutation/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MUTATION KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**Gate M** (incremental mutation testing) + **Gate M2** helpers (test-layer detection used by `src/mock-policy/`). Pre-push quality gate. TypeScript-only; uses Stryker.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 12 pre-commit gates (Gate 0-11), 8 pre-push gates, Sprint Flow (6 phases), and Delphi multi-expert review (>=90% consensus).",
|
|
6
6
|
"author": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
package/plugins/dsh/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boyingliu01/dsh-plugin-xp-gate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "XP-Gate deterministic quality gates + AI workflow skills as a DeepSeek Harness (DSH) native plugin: gate-check / gate-principles / gate-arch tools + 12 SKILL.md skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Qoder. Includes 12 pre-commit gates (Gate 0-11), 8 pre-push gates, Sprint Flow (6 phases), and Delphi multi-expert review (>=90% consensus).",
|
|
6
6
|
"author": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
package/principles/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# PRINCIPLES CHECKER MODULE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Clean Code & SOLID principles checker — **Gate 4** of pre-commit. 14 rules × 9 language adapters, SARIF 2.1.0 output. Houses the **Boy Scout Rule** enforcement engine (Gate 6) and warning-baseline storage.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
5
|
-
**Branch:**
|
|
6
|
-
**Version:** 0.
|
|
3
|
+
**Generated:** 2026-10-13
|
|
4
|
+
**Commit:** 05a08fcf
|
|
5
|
+
**Branch:** main
|
|
6
|
+
**Version:** 0.21.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|