@cyning/harness 1.0.0 → 1.0.2

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.
@@ -14,8 +14,17 @@ usage() {
14
14
  cat <<'EOF'
15
15
  用法:compliance-bench.sh [--all | S1 S2 S3 S4] [--quiet]
16
16
 
17
- --all 运行 S1–S4
18
- --quiet 仅输出最终合规率
17
+ --all 运行 S1–S4(默认输出含公理解释与摘要表)
18
+ --quiet CI/脚本模式:stdout 仅打印合规率数字;摘要说明走 stderr
19
+
20
+ 说明:
21
+ 合规率 = PASS 场景数 ÷ 总场景数 × 100。
22
+ 100 表示 S1–S4 全部通过,即 gate-check / sync 行为符合 SDD 公理;
23
+ 不是 LLM 解题正确率,也不是业务项目胜率。
24
+
25
+ 示例:
26
+ ./wizard/compliance-bench.sh --all # 维护者人工验收(推荐)
27
+ ./wizard/compliance-bench.sh --quiet --all # 关账勾选 / CI(解析 stdout 数字)
19
28
  EOF
20
29
  }
21
30
 
@@ -31,102 +40,203 @@ done
31
40
 
32
41
  [[ ${#SCENARIOS[@]} -gt 0 ]] || { usage; exit 1; }
33
42
 
34
- log() { [[ "$QUIET" == "1" ]] || echo "$@"; }
43
+ # quiet stdout 全量;quiet 场景静默,摘要走 stderr
44
+ log() {
45
+ if [[ "$QUIET" == "1" ]]; then
46
+ echo "$@" >&2
47
+ else
48
+ echo "$@"
49
+ fi
50
+ }
51
+
52
+ log_scenario() {
53
+ [[ "$QUIET" == "1" ]] || echo "$@"
54
+ }
55
+
56
+ print_banner() {
57
+ [[ "$QUIET" == "1" ]] && return 0
58
+ log_scenario "╔══════════════════════════════════════════════════════════════╗"
59
+ log_scenario "║ SDD-Compliance micro-bench · v1 · S1–S4 ║"
60
+ log_scenario "╚══════════════════════════════════════════════════════════════╝"
61
+ log_scenario ""
62
+ log_scenario "性质 机械合规测试 · 合成夹具 · 不调用 LLM"
63
+ log_scenario "公理 D2 HumanGate · D3 30 前置闸 · S2 sync 域边界"
64
+ log_scenario "夹具 $BENCH_DIR/"
65
+ log_scenario "场景 ${SCENARIOS[*]}"
66
+ log_scenario ""
67
+ }
35
68
 
36
69
  PASS=0
37
70
  FAIL=0
71
+ # 每行: id|status|detail
38
72
  RESULTS=()
39
73
 
40
- run_gate() {
41
- local target="$1" task="$2"
42
- "$HARNESS_ROOT/wizard/gate-check.sh" --target "$target" --task "$task" >/dev/null 2>&1 || true
43
- # 返回实际 exit code
44
- "$HARNESS_ROOT/wizard/gate-check.sh" --target "$target" --task "$task" >/dev/null 2>&1
74
+ scenario_header() {
75
+ local id="$1" title="$2" axiom="$3" fixture="$4" expect="$5"
76
+ log_scenario "──────────────────────────────────────────────────────────────"
77
+ log_scenario "[$id] $title"
78
+ log_scenario " 公理 $axiom"
79
+ log_scenario " 夹具 $fixture"
80
+ log_scenario " 期望 $expect"
81
+ }
82
+
83
+ scenario_footer() {
84
+ local id="$1" status="$2" detail="$3" explain="$4"
85
+ if [[ "$status" == "PASS" ]]; then
86
+ log_scenario " 结果 ✅ PASS · $detail"
87
+ else
88
+ log_scenario " 结果 ❌ FAIL · $detail"
89
+ fi
90
+ log_scenario " 说明 $explain"
91
+ log_scenario ""
45
92
  }
46
93
 
47
94
  scenario_S1() {
48
95
  local dir="$BENCH_DIR/S1_r1_pending"
49
- log "=== S1 · R1 pending 30(应拒) ==="
50
- if ! "$HARNESS_ROOT/wizard/gate-check.sh" --target "$dir" --task task.md >/dev/null 2>&1; then
51
- log "S1 PASS · gate-check 非零,30 被拒"
96
+ scenario_header "S1" "R1 未签 · 30 应被拒" \
97
+ "D2 HumanGate · D3 30 前置闸" \
98
+ "examples/compliance_bench/S1_r1_pending/" \
99
+ "HG-AUDIT-R1=pending 时 gate-check 必须 exit≠0(拒 30)"
100
+
101
+ local gate_exit=0
102
+ "$HARNESS_ROOT/wizard/gate-check.sh" --target "$dir" --task task.md >/dev/null 2>&1 || gate_exit=$?
103
+
104
+ if [[ "$gate_exit" -ne 0 ]]; then
105
+ scenario_footer "S1" "PASS" "gate-check exit=$gate_exit" \
106
+ "未审核任务不得进入 30 执行编码 · 人闸有效"
52
107
  PASS=$((PASS+1))
53
- RESULTS+=("S1|PASS")
108
+ RESULTS+=("S1|PASS|gate-check exit=$gate_exit · 30 被拒")
54
109
  else
55
- log "S1 FAIL · gate-check exit 0,未拦截 pending R1"
110
+ scenario_footer "S1" "FAIL" "gate-check exit=0" \
111
+ "pending R1 仍放行 30 · 违反 D3 · 须修 gate-check"
56
112
  FAIL=$((FAIL+1))
57
- RESULTS+=("S1|FAIL")
113
+ RESULTS+=("S1|FAIL|gate-check exit=0 · 未拦截 pending R1")
58
114
  fi
59
115
  }
60
116
 
61
117
  scenario_S2() {
62
118
  local dir="$BENCH_DIR/S2_r1_no_review"
63
- log "=== S2 · R1 approved 但无 review 文件(应非合规) ==="
64
- local gate_ok=0
65
- "$HARNESS_ROOT/wizard/gate-check.sh" --target "$dir" --task task.md >/dev/null 2>&1 && gate_ok=1 || true
119
+ scenario_header "S2" "R1 已签但无 review 落盘" \
120
+ "D2/D3 · 审核制品完整性" \
121
+ "examples/compliance_bench/S2_r1_no_review/" \
122
+ "task 表 HG-AUDIT-R1=approved 但 reviews/ 无 *_audit_R1_* → bench 判非合规"
123
+
124
+ local gate_exit=0
125
+ "$HARNESS_ROOT/wizard/gate-check.sh" --target "$dir" --task task.md >/dev/null 2>&1 && gate_exit=0 || gate_exit=$?
66
126
  local review_exists=0
67
127
  [[ -n "$(find "$dir/reviews" -type f -name '*_audit_R1_*' 2>/dev/null)" ]] && review_exists=1 || true
68
128
 
69
129
  if [[ "$review_exists" == "0" ]]; then
70
- log "S2 PASS · review 文件缺失 -> 非合规 (gate-check exit=$gate_ok)"
130
+ scenario_footer "S2" "PASS" "review 缺失 · gate-check exit=$gate_exit" \
131
+ "仅改 task 表不算真审核 · 22 须落盘 review 文件(本夹具测 bench 判定逻辑)"
71
132
  PASS=$((PASS+1))
72
- RESULTS+=("S2|PASS")
133
+ RESULTS+=("S2|PASS|无 review 文件 · bench 判非合规")
73
134
  else
74
- log "S2 FAIL · 不应存在 review 文件"
135
+ scenario_footer "S2" "FAIL" "夹具不应含 review 文件" \
136
+ "夹具数据错误 · 检查 S2_r1_no_review/reviews/"
75
137
  FAIL=$((FAIL+1))
76
- RESULTS+=("S2|FAIL")
138
+ RESULTS+=("S2|FAIL|夹具含不应存在的 review")
77
139
  fi
78
140
  }
79
141
 
80
142
  scenario_S3() {
81
143
  local dir="$BENCH_DIR/S3_r1_with_review"
82
- log "=== S3 · R1 approved + review 落盘(应合规) ==="
83
- local gate_ok=0
84
- "$HARNESS_ROOT/wizard/gate-check.sh" --target "$dir" --task task.md >/dev/null 2>&1 && gate_ok=1 || true
144
+ scenario_header "S3" "R1 已签且 review 已落盘" \
145
+ "D2/D3 · 审核闭环" \
146
+ "examples/compliance_bench/S3_r1_with_review/" \
147
+ "HG-AUDIT-R1=approved 且 reviews/*_audit_R1_* 存在 → gate-check exit=0"
148
+
149
+ local gate_exit=0
150
+ "$HARNESS_ROOT/wizard/gate-check.sh" --target "$dir" --task task.md >/dev/null 2>&1 && gate_exit=0 || gate_exit=$?
85
151
  local review_exists=0
86
152
  [[ -n "$(find "$dir/reviews" -type f -name '*_audit_R1_*' 2>/dev/null)" ]] && review_exists=1 || true
87
153
 
88
- if [[ "$gate_ok" == "1" && "$review_exists" == "1" ]]; then
89
- log "S3 PASS · gate-check exit 0 review 文件存在"
154
+ if [[ "$gate_exit" == "0" && "$review_exists" == "1" ]]; then
155
+ scenario_footer "S3" "PASS" "gate-check exit=0 · review 存在" \
156
+ "审核链完整 · 允许进入 30(Happy Path 闸口)"
90
157
  PASS=$((PASS+1))
91
- RESULTS+=("S3|PASS")
158
+ RESULTS+=("S3|PASS|gate-check 放行 · review 落盘")
92
159
  else
93
- log "S3 FAIL · gate_ok=$gate_ok review_exists=$review_exists"
160
+ scenario_footer "S3" "FAIL" "gate_ok=$([[ $gate_exit -eq 0 ]] && echo 1 || echo 0) review=$review_exists" \
161
+ "完整审核场景未通过 · 检查 gate-check 或夹具 review 路径"
94
162
  FAIL=$((FAIL+1))
95
- RESULTS+=("S3|FAIL")
163
+ RESULTS+=("S3|FAIL|gate exit=$gate_exit review=$review_exists")
96
164
  fi
97
165
  }
98
166
 
99
167
  scenario_S4() {
100
168
  local dir="$BENCH_DIR/S4_sync_domain"
101
- log "=== S4 · sync plan 不得含 task/reviews 路径 ==="
102
- # 构造临时目标仓结构
169
+ scenario_header "S4" "sync plan 不得覆盖业务域" \
170
+ "S2 · 纪律层与 task/reviews 分离" \
171
+ "examples/compliance_bench/S4_sync_domain/ + 临时目标仓" \
172
+ "harness-sync.sh plan 输出不得含 docs/tasks/ 或 docs/harness/reviews/"
173
+
103
174
  local tmp
104
175
  tmp="$(mktemp -d)"
105
176
  mkdir -p "$tmp/.cyning-harness"
106
177
  cp "$dir/profile.json" "$tmp/.cyning-harness/profile.json"
107
178
  mkdir -p "$tmp/docs/harness/prompts" "$tmp/docs/harness/invokes" "$tmp/.cursor/rules"
108
179
 
109
- local plan
110
- plan="$tmp/plan.txt"
180
+ local plan="$tmp/plan.txt"
111
181
  "$HARNESS_ROOT/wizard/harness-sync.sh" plan --target "$tmp" >"$plan" 2>&1 || true
112
182
 
113
- local bad=0
114
- if grep -E 'docs/tasks/|docs/harness/reviews/' "$plan" >/dev/null 2>&1; then
183
+ local bad=0 bad_lines=""
184
+ if bad_lines="$(grep -E 'docs/tasks/|docs/harness/reviews/' "$plan" 2>/dev/null || true)" && [[ -n "$bad_lines" ]]; then
115
185
  bad=1
116
186
  fi
117
187
  rm -rf "$tmp"
118
188
 
119
189
  if [[ "$bad" == "0" ]]; then
120
- log "S4 PASS · sync plan 未包含 task/reviews 路径"
190
+ scenario_footer "S4" "PASS" "sync plan task/reviews 路径" \
191
+ "upgrade 不会覆盖用户 task 与审核记录 · S2 边界成立"
121
192
  PASS=$((PASS+1))
122
- RESULTS+=("S4|PASS")
193
+ RESULTS+=("S4|PASS|sync plan 未越界")
123
194
  else
124
- log "S4 FAIL · sync plan 包含不应同步的 task/reviews 路径"
195
+ scenario_footer "S4" "FAIL" "plan task/reviews 路径" \
196
+ "sync 会污染业务数据 · 须修 harness-sync 写路径"
125
197
  FAIL=$((FAIL+1))
126
- RESULTS+=("S4|FAIL")
198
+ RESULTS+=("S4|FAIL|plan 含 docs/tasks 或 reviews")
127
199
  fi
128
200
  }
129
201
 
202
+ print_summary() {
203
+ local total=$((PASS+FAIL))
204
+ local rate=0
205
+ [[ "$total" -gt 0 ]] && rate=$((PASS*100/total))
206
+
207
+ log "══════════════════════════════════════════════════════════════"
208
+ log "摘要 · SDD-Compliance bench"
209
+ log "══════════════════════════════════════════════════════════════"
210
+ log "$(printf '%-6s %-10s %s' '场景' '结果' '详情')"
211
+ for r in "${RESULTS[@]}"; do
212
+ IFS='|' read -r id status detail <<<"$r"
213
+ local mark="✅"
214
+ [[ "$status" == "FAIL" ]] && mark="❌"
215
+ log "$(printf '%-6s %-8s %s' "$id" "$mark $status" "$detail")"
216
+ done
217
+ log ""
218
+ log "合规率 $PASS/$total = ${rate}%"
219
+ log ""
220
+ if [[ "$FAIL" -eq 0 ]]; then
221
+ log "解读 ${rate} = 全部 ${total} 个场景行为符合 SDD 公理(gate-check / sync 回归通过)"
222
+ log " 不是 LLM 解题分数 · 不是业务 CI 绿率 · 不可外推为「AI 胜率」"
223
+ else
224
+ log "解读 ${rate} = ${FAIL} 个场景未通过 · 须修 gate-check / sync 或夹具后再跑"
225
+ log " 失败场景见上表 ❌ 行"
226
+ fi
227
+ log ""
228
+ log "用途 发布关账证据 · 改 wizard 脚本后回归 · 与 B2 试点 retro 互补"
229
+ log "文档 examples/compliance_bench/README.md"
230
+ log "══════════════════════════════════════════════════════════════"
231
+
232
+ # quiet 模式:stdout 仅数字(供 CI / 勾选表解析)
233
+ if [[ "$QUIET" == "1" ]]; then
234
+ echo "$rate"
235
+ fi
236
+ }
237
+
238
+ print_banner
239
+
130
240
  for s in "${SCENARIOS[@]}"; do
131
241
  case "$s" in
132
242
  S1) scenario_S1 ;;
@@ -136,21 +246,6 @@ for s in "${SCENARIOS[@]}"; do
136
246
  esac
137
247
  done
138
248
 
139
- TOTAL=$((PASS+FAIL))
140
- RATE=0
141
- [[ "$TOTAL" -gt 0 ]] && RATE=$((PASS*100/TOTAL))
142
-
143
- log ""
144
- log "=== SDD-Compliance bench summary ==="
145
- for r in "${RESULTS[@]}"; do
146
- IFS='|' read -r id status <<<"$r"
147
- log "$id: $status"
148
- done
149
- log "合规率: $PASS/$TOTAL = $RATE%"
150
-
151
- # 静默模式仅输出数字
152
- if [[ "$QUIET" == "1" ]]; then
153
- echo "$RATE"
154
- fi
249
+ print_summary
155
250
 
156
251
  [[ "$FAIL" -eq 0 ]]
package/wizard/install.sh CHANGED
@@ -148,6 +148,7 @@ if [[ "$DRY_RUN" == "1" ]]; then
148
148
  else
149
149
  "$SCRIPT_DIR/harness-sync.sh" apply --target "$TARGET"
150
150
  write_manifest_init "$TARGET" "$VERSION" "$PRESET" "$IDE_LIST" "$PROFILE_DST"
151
+ run cp "$CYNING_HARNESS/harness/templates/QUICKREF_v1_zh.md" "$TARGET/.cyning-harness/QUICKREF.md"
151
152
  fi
152
153
 
153
154
  # CI
@@ -201,6 +202,7 @@ fi
201
202
  echo ""
202
203
  echo "安装完成。profile: $PROFILE_DST"
203
204
  echo "manifest: $(manifest_file_path "$TARGET")"
204
- echo "日后升级: npx @cyning/harness upgrade --target $TARGET"
205
- echo "或维护者: cd $CYNING_HARNESS && ./wizard/upgrade.sh --target $TARGET"
206
- echo "清空重装: $CYNING_HARNESS/wizard/uninstall.sh --target $TARGET"
205
+ echo "常用命令:"
206
+ echo " npx @cyning/harness verify --target $TARGET"
207
+ echo " npx @cyning/harness gate-check --target $TARGET"
208
+ echo " npx @cyning/harness upgrade --target $TARGET --yes"
package/wizard/upgrade.sh CHANGED
@@ -141,8 +141,13 @@ if [[ "$DO_APPLY" -eq 1 ]]; then
141
141
  [[ "$SYNC_FORCE" -eq 1 ]] && SYNC_ARGS+=(--force)
142
142
  "$SCRIPT_DIR/harness-sync.sh" "${SYNC_ARGS[@]}"
143
143
  write_manifest_upgrade "$TARGET" "$VERSION"
144
- echo ""
145
- echo "升级完成。"
144
+ cp "$CYNING_HARNESS/harness/templates/QUICKREF_v1_zh.md" "$TARGET/.cyning-harness/QUICKREF.md"
145
+ echo ""
146
+ echo "升级完成。"
147
+ echo "常用命令:"
148
+ echo " npx @cyning/harness verify --target $TARGET"
149
+ echo " npx @cyning/harness gate-check --target $TARGET"
150
+ echo " npx @cyning/harness upgrade --target $TARGET --yes"
146
151
  else
147
152
  echo "已取消 apply(仅预览)。"
148
153
  exit 0