فهرست منبع

test(skills): harden section-map gates per adversarial review (3 findings)

Codex refuter (lane v2-refute-g2) refuted the first cut:
1. The svg drift gate sat below the node/curl skip guards — a
   node-less runner exited 0 without running a check that needs only
   grep/awk. Relocated into the static section, before the guards.
2. summon's count gate (14/13) was rename-blind: swapping a section
   name on either side kept counts intact. Upgraded to strict
   alias-resolved first-token matching (Modes->Toolbox, CLI->Main,
   Transcript/Distill excepted as banner-less) — a rename now names
   the diverging keys in the failure.
3. Boxed banners' closing ruler line was unvalidated — deleting one
   went unnoticed. Even-ruler-count parity check added.
Replayed: rename -> DRIFT names Cache/Sessions; deleted ruler ->
odd-count FAIL; both suites green on clean tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0xDarkMatter 1 هفته پیش
والد
کامیت
c47773cb2b
2فایلهای تغییر یافته به همراه76 افزوده شده و 69 حذف شده
  1. 31 24
      skills/summon/tests/run.sh
  2. 45 45
      skills/svg-brand-tint-ops/tests/run.sh

+ 31 - 24
skills/summon/tests/run.sh

@@ -48,13 +48,14 @@ SUMMON_PY_RC=0
 # pass) — that is the rot mode this guard exists to catch: a docstring/map
 # format change that yields zero names.
 #
-# Strict name-equality matching is intentionally NOT used: the docstring and
-# the banner headers carry different labels for several sections
-# ("DESIGN(term)"↔"DESIGN", "Modes (…)"↔"Toolbox modes", "CLI entry"↔"Main")
-# and the map lists "Transcript/Distill" with no banner of its own, so a
-# name gate would false-fail on the current file. The count gate is the
-# mechanical structural-sync check that stays green and still catches every
-# add/remove mutation.
+# Matching is STRICT on alias-resolved first-token keys (upgraded from a
+# count gate per adversarial review — counts stay 14/13 under a rename, so
+# structural drift slipped by). The docstring and banners carry different
+# labels for a few sections ("DESIGN(term)"↔"DESIGN:", "Modes (…)"↔"Toolbox
+# modes:", "CLI entry"↔"Main"), so those are an explicit alias table, and
+# "Transcript/Distill" (implemented inline, banner-less) is an explicit
+# exception. Anything else that diverges — including a rename on either
+# side — is drift.
 GP=0; GF=0
 ok(){ GP=$((GP+1)); printf '  PASS  %s\n' "$1"; }
 no(){ GF=$((GF+1)); printf '  FAIL  %s\n' "$1"; }
@@ -79,28 +80,34 @@ ban_sections="$(awk '
 ' "$SRC")"
 bc="$(printf '%s\n' "$ban_sections" | grep -c . || true)"
 
-# Expected counts — the docstring lists one more conceptual section than the
-# body has banners ("Transcript/Distill" is implemented inline, banner-less).
-# Bump EXPECT_DOC when the 'Sections:' map grows; EXPECT_BAN when a banner is
-# added or removed. Both move together whenever the file's outline changes.
-EXPECT_DOC=14
-EXPECT_BAN=13
+# Normalize a section label to its comparison key: first token, with any
+# "(...)" suffix and trailing ":" stripped ("DESIGN(term)" -> "DESIGN",
+# "Toolbox modes: rebind…" -> "Toolbox").
+norm_key() { awk '{ t=$1; sub(/\(.*$/,"",t); sub(/:$/,"",t); print t }'; }
+doc_keys="$(printf '%s\n' "$doc_sections" | norm_key | sed \
+  -e 's/^Modes$/Toolbox/' \
+  -e 's/^CLI$/Main/' \
+  | grep -v '^Transcript' | sort -u)"
+ban_keys="$(printf '%s\n' "$ban_sections" | norm_key | sort -u)"
 
-# forward direction (the map side): the declared section count is stable
 if [[ "$dc" -eq 0 ]]; then
-  no "section-map (docstring) EMPTY PARSE: 0 sections — 'Sections:' line missing or unparseable (expected $EXPECT_DOC)"
-elif [[ "$dc" -eq "$EXPECT_DOC" ]]; then
-  ok "section-map (docstring): $dc sections declared (expected $EXPECT_DOC)"
+  no "section-map (docstring) EMPTY PARSE: 0 sections — 'Sections:' line missing or unparseable"
+elif [[ "$bc" -eq 0 ]]; then
+  no "section-map (body) EMPTY PARSE: 0 banners — banner format changed"
+elif [[ "$doc_keys" == "$ban_keys" ]]; then
+  ok "section-map: docstring ($dc) <-> banners ($bc) match after alias resolution"
 else
-  no "section-map (docstring) DRIFT: parsed $dc, expected $EXPECT_DOC"
+  diverged="$(comm -3 <(printf '%s\n' "$doc_keys") <(printf '%s\n' "$ban_keys") | tr -d '\t' | paste -sd', ' -)"
+  no "section-map DRIFT — docstring and banners disagree on: ${diverged:-<unknown>}"
 fi
-# reverse direction (the body side): the banner section count is stable
-if [[ "$bc" -eq 0 ]]; then
-  no "section-map (body) EMPTY PARSE: 0 banners — banner format changed (expected $EXPECT_BAN)"
-elif [[ "$bc" -eq "$EXPECT_BAN" ]]; then
-  ok "section-map (body): $bc banner sections (expected $EXPECT_BAN)"
+
+# Boxed-banner parity: each banner is a 3-line box (=== / title / ===); an
+# odd ruler-line count means a box's closing line was deleted.
+rulers="$(grep -cE '^# ={20,}$' "$SRC" || true)"
+if (( rulers > 0 && rulers % 2 == 0 )); then
+  ok "section-map: $rulers banner ruler lines (even — boxes intact)"
 else
-  no "section-map (body) DRIFT: parsed $bc, expected $EXPECT_BAN"
+  no "section-map: ruler-line count $rulers (odd or zero) — a banner box is broken"
 fi
 
 echo "=== section-map drift gate: $GP passed, $GF failed ==="

+ 45 - 45
skills/svg-brand-tint-ops/tests/run.sh

@@ -34,6 +34,51 @@ has "index ships the iso-contour tracer" "isoContours" "$idx"
 has "index has the Image Trace panel" "Image Trace" "$idx"
 [[ -f "$SAMPLE" ]] && ok "sample.svg present" || no "sample.svg missing"
 
+# --- section-map drift gate (assets/index.html: guard comment ↔ // === markers) ---
+# index.html is a deliberately single-file studio; its top <script> guard
+# comment lists the `// === NAME ===` banner sections so the file is
+# navigable. This gate keeps the guard list and the body markers in sync
+# bidirectionally and FAILS LOUDLY if either side parses to zero names — the
+# classic rot mode where a guard-comment/marker format change silently yields
+# an empty list and the check would otherwise vacuously pass.
+map_names="$(awk '
+  /Sections \(grep/ { cap=1; sub(/.*:[[:space:]]*/,"",$0); blob=blob $0 " "; if ($0 ~ /\*\//) cap=0; next }
+  cap { if ($0 ~ /\*\//) { cap=0; next } blob=blob $0 " " }
+  END { gsub(/·/,"\n",blob); n=split(blob,a,"\n");
+        for (i=1;i<=n;i++){ s=a[i]; sub(/^[[:space:]]+/,"",s); sub(/[[:space:]]+$/,"",s); if (s!="") print s } }
+' "$INDEX")"
+mark_names="$(grep -E '^// === .* ===$' "$INDEX" | sed -E 's|^// === (.*) ===$|\1|')"
+dc="$(printf '%s\n' "$map_names"  | grep -c . || true)"
+mc="$(printf '%s\n' "$mark_names" | grep -c . || true)"
+# empty-parse guard: either side unparseable is a hard fail (never a silent pass)
+if [[ "$dc" -gt 0 && "$mc" -gt 0 ]]; then
+  ok "section-map parses (guard=$dc names, body=$mc markers)"
+else
+  no "section-map EMPTY PARSE (guard=$dc, body=$mc) — guard comment or marker format changed"
+fi
+# forward: every guard-listed section has a matching // === marker
+fwd_miss=""
+while IFS= read -r n; do
+  [[ -z "$n" ]] && continue
+  grep -Fxq -- "$n" <<< "$mark_names" || fwd_miss="$fwd_miss $n"
+done <<< "$map_names"
+if [[ -z "$fwd_miss" ]]; then
+  ok "forward: every guard-listed section has a // === marker"
+else
+  no "forward: guard sections with no marker:${fwd_miss}"
+fi
+# reverse: every // === marker is present in the guard list
+rev_miss=""
+while IFS= read -r n; do
+  [[ -z "$n" ]] && continue
+  grep -Fxq -- "$n" <<< "$map_names" || rev_miss="$rev_miss $n"
+done <<< "$mark_names"
+if [[ -z "$rev_miss" ]]; then
+  ok "reverse: every // === marker is listed in the guard comment"
+else
+  no "reverse: body markers missing from guard:${rev_miss}"
+fi
+
 # ── runtime: needs node + curl ─────────────────────────────────────────────
 if ! command -v node >/dev/null 2>&1; then echo "  SKIP  node not found — runtime checks skipped"; echo "=== $PASS passed, $FAIL failed ==="; [[ "$FAIL" -eq 0 ]] || exit 1; exit 0; fi
 if ! command -v curl >/dev/null 2>&1; then echo "  SKIP  curl not found — runtime checks skipped"; echo "=== $PASS passed, $FAIL failed ==="; [[ "$FAIL" -eq 0 ]] || exit 1; exit 0; fi
@@ -86,50 +131,5 @@ fi
 kill "$SRV" >/dev/null 2>&1; trap - EXIT
 rm -f "$LOG" "$PORT_FILE" 2>/dev/null
 
-# --- section-map drift gate (assets/index.html: guard comment ↔ // === markers) ---
-# index.html is a deliberately single-file studio; its top <script> guard
-# comment lists the `// === NAME ===` banner sections so the file is
-# navigable. This gate keeps the guard list and the body markers in sync
-# bidirectionally and FAILS LOUDLY if either side parses to zero names — the
-# classic rot mode where a guard-comment/marker format change silently yields
-# an empty list and the check would otherwise vacuously pass.
-map_names="$(awk '
-  /Sections \(grep/ { cap=1; sub(/.*:[[:space:]]*/,"",$0); blob=blob $0 " "; if ($0 ~ /\*\//) cap=0; next }
-  cap { if ($0 ~ /\*\//) { cap=0; next } blob=blob $0 " " }
-  END { gsub(/·/,"\n",blob); n=split(blob,a,"\n");
-        for (i=1;i<=n;i++){ s=a[i]; sub(/^[[:space:]]+/,"",s); sub(/[[:space:]]+$/,"",s); if (s!="") print s } }
-' "$INDEX")"
-mark_names="$(grep -E '^// === .* ===$' "$INDEX" | sed -E 's|^// === (.*) ===$|\1|')"
-dc="$(printf '%s\n' "$map_names"  | grep -c . || true)"
-mc="$(printf '%s\n' "$mark_names" | grep -c . || true)"
-# empty-parse guard: either side unparseable is a hard fail (never a silent pass)
-if [[ "$dc" -gt 0 && "$mc" -gt 0 ]]; then
-  ok "section-map parses (guard=$dc names, body=$mc markers)"
-else
-  no "section-map EMPTY PARSE (guard=$dc, body=$mc) — guard comment or marker format changed"
-fi
-# forward: every guard-listed section has a matching // === marker
-fwd_miss=""
-while IFS= read -r n; do
-  [[ -z "$n" ]] && continue
-  grep -Fxq -- "$n" <<< "$mark_names" || fwd_miss="$fwd_miss $n"
-done <<< "$map_names"
-if [[ -z "$fwd_miss" ]]; then
-  ok "forward: every guard-listed section has a // === marker"
-else
-  no "forward: guard sections with no marker:${fwd_miss}"
-fi
-# reverse: every // === marker is present in the guard list
-rev_miss=""
-while IFS= read -r n; do
-  [[ -z "$n" ]] && continue
-  grep -Fxq -- "$n" <<< "$map_names" || rev_miss="$rev_miss $n"
-done <<< "$mark_names"
-if [[ -z "$rev_miss" ]]; then
-  ok "reverse: every // === marker is listed in the guard comment"
-else
-  no "reverse: body markers missing from guard:${rev_miss}"
-fi
-
 echo "=== $PASS passed, $FAIL failed ==="
 [[ "$FAIL" -eq 0 ]] || exit 1