fix(gates): report an unparsed routing clause beside a parsing sibling
boundary_clause_status() ran BOUNDARY_ARROW.search() and _arrow_targets()
over the whole description, so one arrow clause that parsed suppressed the
diagnostic for every other clause in it. A backticked hyphenated routing
target wrapped across lines in a folded scalar was therefore silently
unchecked -- no error, no suggestion, exit 0 -- whenever the description
carried one other clause that parsed. Written bare, the same wrap errors
correctly. That is the shape #100 regressed on.
The check is now per clause. Nothing that passed starts failing: all 68
routing targets across the 38 SKILL.md files resolved before and still do.
26 of those descriptions carry more than one arrow clause, so the
suppression was live across two thirds of the corpus, not an edge case.
validate-skill.bats pins the shape. test-adr0020-targets.sh's comment
described the #100 regression as a backticked wrap; the historical text was
unbackticked, which is precisely the shape the gate did not catch.
Also closes three README misroutes the branch left in the enforcement
layer: CompositionNote.yml's message, agent-description-quality.md:58 and
vale-wrap.sh's header still sent overflow to a skill-root README.md and
named the two skills ADR-0025 merged away. 1ec3e8a fixed the prose and
missed the rules that enforce it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2
This commit is contained in:
@@ -945,6 +945,48 @@ make_hand_invoked_skill() {
|
||||
assert_output --partial "no target could be read"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ADR-0020 — the unparsed diagnostic is PER CLAUSE, not per description
|
||||
#
|
||||
# boundary_clause_status() used to test `BOUNDARY_ARROW.search(description) and
|
||||
# not _arrow_targets(description)`. Both operands took the WHOLE description,
|
||||
# so ONE arrow clause that parsed suppressed the diagnostic for every other
|
||||
# clause beside it.
|
||||
#
|
||||
# The shape that hides there is a backticked hyphenated target wrapped across
|
||||
# the line break of a `>` folded scalar: the fold turns `` `fixture-sibling- ``
|
||||
# / `` skill` `` into `fixture-sibling- skill`, which no extractor can read.
|
||||
# Written BARE the same wrap is reported correctly, so the two spellings
|
||||
# disagreed. 26 of this repo's 38 skill descriptions carry more than one arrow
|
||||
# clause, which is how wide the suppression was. This is the #100 regression
|
||||
# class: no ERROR, no SUGGESTION, exit 0.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@test "ADR-0020: an unparsed arrow clause is reported even when a sibling clause parses" {
|
||||
local skill
|
||||
skill="$(make_fixture_tree "$TMPDIR/tree" "my-skill")"
|
||||
# Written by hand rather than through make_sized_skill: the `>` folded
|
||||
# scalar and the wrap INSIDE the backticks are the fixture. The second
|
||||
# clause parses and resolves against the fixture sibling, and that is what
|
||||
# used to silence the first.
|
||||
cat > "$skill/SKILL.md" <<'EOF'
|
||||
---
|
||||
name: my-skill
|
||||
description: >
|
||||
Use when doing the thing. Not the other thing -> `fixture-sibling-
|
||||
skill`. Not a third thing -> `fixture-sibling-skill`.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
---
|
||||
|
||||
word word word word word word word word word word
|
||||
EOF
|
||||
run bash "$SCRIPT" "$skill"
|
||||
assert_success
|
||||
assert_output --partial "no target could be read"
|
||||
refute_output --partial "has no boundary clause"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Encoding, write side: sys.stdout/stderr.reconfigure(encoding='utf-8')
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user