feat: build in organized-feedback validation script and update docs
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
SKILL_FILE="$SKILL_ROOT/SKILL.md"
|
||||
INPUT_EXAMPLE="$SKILL_ROOT/examples/input-pr-review.md"
|
||||
OUTPUT_EXAMPLE="$SKILL_ROOT/examples/output-organized-feedback.md"
|
||||
|
||||
if ! command -v rg >/dev/null 2>&1; then
|
||||
echo "FAIL: rg is required but was not found in PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$SKILL_FILE" ]]; then
|
||||
echo "FAIL: missing $SKILL_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for example_file in "$INPUT_EXAMPLE" "$OUTPUT_EXAMPLE"; do
|
||||
if [[ ! -f "$example_file" ]]; then
|
||||
echo "FAIL: missing $example_file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
anchored_patterns=(
|
||||
'^## Inputs$'
|
||||
'^## Hard Gates$'
|
||||
'^## Classification Taxonomy$'
|
||||
'^## RFC Subfields$'
|
||||
'^## Processing Flow$'
|
||||
'^## Interaction-Only Coverage Audit$'
|
||||
'^## Unknown Handling$'
|
||||
'^## Final File Format$'
|
||||
'^## Output Discipline$'
|
||||
'^- `Change-Scope`: how broad the requested change is\.$'
|
||||
'^ - `local`: .+$'
|
||||
'^ - `implement`: .+$'
|
||||
'^ - `api-change`: .+$'
|
||||
'^ - `requirement-change`: .+$'
|
||||
'^- `Necessity`: how strongly the change is required\.$'
|
||||
'^ - `nice-to-have`: .+$'
|
||||
'^ - `should-fix`: .+$'
|
||||
'^ - `must-fix`: .+$'
|
||||
'^- `All-Source-Refs`: every source reference found in the interaction$'
|
||||
'^- `Covered-Source-Refs`: refs that are represented in the organized output$'
|
||||
'^- `Missing-Source-Refs`: refs that are present in the interaction but not yet covered$'
|
||||
'^Source reference format rule:$'
|
||||
'^- Use `R` \+ PR numbering path from the source markdown\.$'
|
||||
'^- Example mapping: `Comment 42\.1\.1` -> `R42\.1\.1`, `Reply 42\.1\.1\.1` -> `R42\.1\.1\.1`\.$'
|
||||
)
|
||||
|
||||
for pattern in "${anchored_patterns[@]}"; do
|
||||
if ! rg -n -q --pcre2 "$pattern" "$SKILL_FILE"; then
|
||||
echo "FAIL: missing required rule -> $pattern"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for pattern in "All refs" "Covered refs" "Missing refs"; do
|
||||
if rg -Fq "$pattern" "$SKILL_FILE"; then
|
||||
echo "FAIL: legacy alias found -> $pattern"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for pattern in "output path" "interaction" "coverage audit" "unknown count" "reflection pass" "Unknown Items"; do
|
||||
if ! rg -Fq -- "$pattern" "$SKILL_FILE"; then
|
||||
echo "FAIL: missing required rule -> $pattern"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! rg -Fq -- "unknown(>=1)" "$SKILL_FILE" || ! rg -Fq -- "反思复判" "$SKILL_FILE"; then
|
||||
echo "FAIL: missing unknown reflection rule semantics (unknown>=1 + 反思复判)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if rg -Fq "Coverage Audit" "$OUTPUT_EXAMPLE"; then
|
||||
echo "FAIL: coverage audit must not appear in $OUTPUT_EXAMPLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! rg -n -q --pcre2 '^## Organized Feedback$' "$OUTPUT_EXAMPLE"; then
|
||||
echo "FAIL: missing ## Organized Feedback in $OUTPUT_EXAMPLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! rg -Fq "Source-Refs:" "$OUTPUT_EXAMPLE"; then
|
||||
echo "FAIL: missing Source-Refs: line in $OUTPUT_EXAMPLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! rg -n -q --pcre2 '^- Source-Refs: R[0-9]+(\.[0-9]+)+(, R[0-9]+(\.[0-9]+)+)*$' "$OUTPUT_EXAMPLE"; then
|
||||
echo "FAIL: Source-Refs lines must use R-prefixed numeric reference format"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
awk '
|
||||
BEGIN {
|
||||
in_section = 0
|
||||
item_count = 0
|
||||
item_has_source_refs = 0
|
||||
saw_item = 0
|
||||
}
|
||||
/^## Organized Feedback$/ {
|
||||
in_section = 1
|
||||
next
|
||||
}
|
||||
in_section && /^## / {
|
||||
if (saw_item && !item_has_source_refs) {
|
||||
bad = 1
|
||||
}
|
||||
exit
|
||||
}
|
||||
in_section {
|
||||
if ($0 ~ /^### Item [0-9]+$/) {
|
||||
if (saw_item && !item_has_source_refs) {
|
||||
bad = 1
|
||||
}
|
||||
saw_item = 1
|
||||
item_has_source_refs = 0
|
||||
item_count++
|
||||
next
|
||||
}
|
||||
if ($0 ~ /^- Source-Refs:/ && saw_item) {
|
||||
item_has_source_refs = 1
|
||||
}
|
||||
}
|
||||
END {
|
||||
if (in_section && saw_item && !item_has_source_refs) {
|
||||
bad = 1
|
||||
}
|
||||
exit bad
|
||||
}
|
||||
' "$OUTPUT_EXAMPLE" || {
|
||||
echo "FAIL: each ### Item in Organized Feedback must include a Source-Refs line"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "PASS: organized-feedback hard gates validated"
|
||||
Reference in New Issue
Block a user