Files
claude_mac/lib/tests/seo-geo-contract.test.sh
T
Bastien Chanot 9681b468e1 test(census): seo/geo agent⇄dispatcher contract locks (C1 P1, pre-reword)
71 locks, flip-proven (7 scratch mutations → 7 FAILs): judge verdict
grammar, FIX BUNDLE + READY-TO-APPLY sentinel, signals handoff, ALL
STEP headers (interiors included, conf#5), collect report, bundle item
fields parsed by L1 appliers, score labels (BDR-010/LRN-011), scoring
blocks, trajectory, envelope keys. Locks existing state — reword
commits must keep this green.

+ plan v3 (challenged 3 lenses FATAL/FATAL/CONCERNS + 1 confirmation
pass FATAL(9), every BLOCKER closed by a named change, §5bis record)
+ directive-language inventory annex (analyzer report).
2026-08-02 01:10:47 +02:00

83 lines
3.5 KiB
Bash

#!/usr/bin/env bash
# lib/tests/seo-geo-contract.test.sh — census: seo/geo agent ⇄ dispatcher
# machine contract (C1 de-prescription, 2026-07-30). Locks every string a
# consumer parses BEFORE the choreography reword, so the reword commits
# prove contract preservation by keeping this green. Complements
# model-routing.test.sh (which already locks model pins + MODE:* +
# COLLECTION COMPLETE).
set -u
R="$(cd "$(dirname "$0")/../.." && pwd)"
pass=0; fail=0
ok() { pass=$((pass+1)); }
ko() { fail=$((fail+1)); printf 'FAIL %s\n' "$1"; }
has() { if grep -qF "$2" "$R/$1"; then ok; else ko "$1 missing: $2"; fi; }
SEO=agents/seo-analyzer.md
GEO=agents/geo-analyzer.md
# 1) judge verdict grammar — DISPATCHER ERROR CONTRACT (skills/seo STEP 1,
# skills/geo STEP 1B) fail-closes on this exact shape
has "$SEO" 'SEO JUDGE — VERDICT: ERROR('
has "$GEO" 'GEO JUDGE — VERDICT: ERROR('
has "skills/seo/SKILL.md" 'SEO JUDGE — VERDICT: ERROR('
has "skills/geo/SKILL.md" 'GEO JUDGE — VERDICT: ERROR('
# 2) fix-bundle section + apply sentinel — parsed by /seo STEP 1b/1.5 and
# /geo STEP 1b/2 before any L1 apply
for f in "$SEO" "$GEO" skills/seo/SKILL.md skills/geo/SKILL.md; do
has "$f" '## FIX BUNDLE'
has "$f" 'READY TO APPLY — awaiting dispatcher confirmation'
done
# 3) signals handoff — judge loads the collect artifact fail-closed
has "$SEO" '.audit/seo-signals-'
has "$GEO" '.audit/geo-signals-'
has "skills/seo/SKILL.md" '.audit/seo-signals-<RUNID_SEO>.md'
has "skills/geo/SKILL.md" '.audit/geo-signals-<RUNID>.md'
# 4) STEP numbering — dispatchers reference agent step ranges literally:
# /seo: "STEP 2-5" collect · "STEP 6-11" seo judge · "STEP 6-12" geo
# judge · "STEP 12-14" seo template · "STEP 13-15" geo template;
# /geo: "STEP 0-5". Lock EVERY step header on the agent side (interiors
# too — merging/renumbering one silently re-points the dispatch ranges)
# and the ranges on the dispatcher side.
for n in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14; do has "$SEO" "## STEP $n —"; done
for n in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do has "$GEO" "## STEP $n —"; done
has "skills/seo/SKILL.md" 'STEP 2-5'
has "skills/seo/SKILL.md" 'STEP 6-11'
has "skills/seo/SKILL.md" 'STEP 6-12'
has "skills/seo/SKILL.md" 'STEP 12-14'
has "skills/seo/SKILL.md" 'STEP 13-15'
has "skills/geo/SKILL.md" 'STEP 0-5'
has "skills/geo/SKILL.md" '6-12, report scoring' # "STEP\n6-12" line-wraps
has "skills/geo/SKILL.md" 'STEP 13-15'
# 5) collect-mode report emission (dispatcher waits on it between phases)
has "$SEO" 'COLLECT REPORT'
has "$GEO" 'COLLECT REPORT'
# 6) bundle-item routing + the item fields the L1 appliers parse
# (the item is pasted verbatim into hotfixer/feater — /seo STEP 1.5)
for f in "$SEO" "$GEO"; do
has "$f" 'applier: hotfixer'
has "$f" 'applier: feater'
has "$f" ' files:'
has "$f" ' current:'
has "$f" ' expected:'
done
has "$SEO" 'applier: bash'
# 7) cross-agent escalation block — merged into SEO.md §11 by /seo STEP 2.
# The emit instruction lives in /seo's DISPATCH PROMPTS, not in the agent
# specs (geo-analyzer.md never mentions it; seo-analyzer.md only once,
# incidentally — NOT locked, it is prose). Lock the dispatcher side only.
has "skills/seo/SKILL.md" 'CROSS-AGENT NOTES TO'
# 8) trajectory block — mandatory in envelopes (/geo audit-end deliverables,
# /seo §1 merge)
has "$SEO" 'TRAJECTORY TO 17/20'
has "$GEO" 'TRAJECTORY TO 17/20'
printf 'seo-geo contract locks: %d pass, %d fail\n' "$pass" "$fail"
[ "$fail" -eq 0 ]