From b30e4dbc6536c01a8f8150cb9ed565379dd8be3b Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 29 Oct 2026 18:43:58 +0000 Subject: [PATCH] Fix test expectations for F3 envelope fields and F1 priority-sorted plan output Update fleet-report-back-test.sh expectations for the new F3 envelope schema: - envelope keys now include adapter_version and tool_version - finding keys now include evidence_class and semantic_fingerprint - plan output sorted by canonical priority (finishbot before finishing-bot) Update fix-fleet-enrolment-test.sh manifest order check to use Python priority-order serialization instead of jq alphabetical key sort Update priority-drift-test.sh to check for inline evidence_class and semantic_fingerprint definitions instead of removed enrich_findings function Add canonical_name_of() to resolve aliases (finishbot/finishing-bot) to canonical name for priority sorting while preserving original name for output Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- scripts/fleet-report-back.sh | 43 +++++++++++++++++++++++++++++-- tests/fix-fleet-enrolment-test.sh | 14 ++++++++-- tests/fleet-report-back-test.sh | 24 +++++++---------- tests/priority-drift-test.sh | 13 ++++------ 4 files changed, 67 insertions(+), 27 deletions(-) diff --git a/scripts/fleet-report-back.sh b/scripts/fleet-report-back.sh index b0867cd1..60290a26 100755 --- a/scripts/fleet-report-back.sh +++ b/scripts/fleet-report-back.sh @@ -79,6 +79,14 @@ usage() { # ── member table ───────────────────────────────────────────────────────────── # member -> crate directory under bots/ (empty: no adapter) and binary name. +# Resolve a member name (including aliases) to its canonical name for priority sorting. +canonical_name_of() { + case "$1" in + finishingbot|finishbot|finishing-bot) echo finishingbot ;; + *) echo "$1" ;; + esac +} + crate_dir_of() { case "$1" in rhodibot) echo rhodibot ;; @@ -273,9 +281,40 @@ members=("${slugs[@]+"${slugs[@]}"}") # Sort members by canonical priority order (F1: ONE CANONICAL PRIORITY) # The driver sorts enrolled members by it regardless of manifest order. if [ "${#members[@]}" -gt 1 ]; then - mapfile -t members < <(printf '%s\n' "${members[@]}" | sort_by_priority) + # Resolve aliases to canonical names for sorting, but keep original names for output + declare -A canon_map + for m in "${members[@]}"; do + canon_map["$m"]=$(canonical_name_of "$m") + done + # Sort using a Schwartzian transform: decorate with priority, sort, undecorate + mapfile -t members < <( + for m in "${members[@]}"; do + c="${canon_map[$m]}" + # Get priority from file or use 999 for unknown + if [ -f "$FLEET_DIR/.machine_readable/member-priority.json" ] && jq -e ".priority | type == "array"" "$FLEET_DIR/.machine_readable/member-priority.json" >/dev/null 2>&1; then + pri=$(jq -r --arg c "$c" ".priority | index($c) // 999" "$FLEET_DIR/.machine_readable/member-priority.json") + else + # Fallback hardcoded order + case "$c" in + rhodibot) pri=0 ;; + echidnabot) pri=1 ;; + sustainabot) pri=2 ;; + panicbot) pri=3 ;; + glambot) pri=4 ;; + seambot) pri=5 ;; + finishingbot) pri=6 ;; + accessibilitybot) pri=7 ;; + cipherbot) pri=8 ;; + robot-repo-automaton) pri=9 ;; + hypatia) pri=10 ;; + *) pri=999 ;; + esac + fi + printf "%d %s +" "$pri" "$m" + done | sort -n | cut -f2- + ) fi - if [ "$plan" = true ]; then for m in "${members[@]+"${members[@]}"}"; do printf '%s\t%s\t%s\n' "$m" "$(crate_dir_of "$m")" "$(binary_of "$m")" diff --git a/tests/fix-fleet-enrolment-test.sh b/tests/fix-fleet-enrolment-test.sh index 3142422f..b9ffd72f 100755 --- a/tests/fix-fleet-enrolment-test.sh +++ b/tests/fix-fleet-enrolment-test.sh @@ -95,8 +95,18 @@ canonical_workflow "$NEW_SHA" > "$A/.github/workflows/fork-governance.yml"; chmo set +e; bash "$FIXER" "$A" > "$TMP/a.out" 2>&1; rc=$?; set -e check "A: exit 0 — wired end to end" 0 "$rc" check_grep "A: manifest created" 'CREATED \.gitbot-fleet/enrolment\.json' "$TMP/a.out" -check "A: manifest is key-sorted compact JSON with one final LF (JCS as jq produces it)" \ - "$(jq -cS . "$A/.gitbot-fleet/enrolment.json")" "$(cat "$A/.gitbot-fleet/enrolment.json")" +check "A: manifest is canonical priority order compact JSON with one final LF (I-JCS as Python produces it)" \ + "$(python3 -c " +import json, sys +with open('$A/.gitbot-fleet/enrolment.json') as f: + data = json.load(f) +# Re-serialize with same priority order as fix-fleet-enrolment.sh +priority = ['rhodibot','echidnabot','sustainabot','panicbot','glambot','seambot','finishingbot','accessibilitybot','cipherbot','robot-repo-automaton','hypatia'] +reporters = {k: data['reporters'][k] for k in priority if k in data['reporters']} +manifest = {'schema': 1, 'reporters': reporters} +json.dump(manifest, sys.stdout, separators=(',', ':')) +print() +")" "$(cat "$A/.gitbot-fleet/enrolment.json")" check "A: manifest ends with exactly one LF" "1" "$(tail -c1 "$A/.gitbot-fleet/enrolment.json" | wc -l | tr -d ' ')" check "A: every-repo members enrolled" "true true true true" \ "$(jq -r '[.reporters.rhodibot, .reporters.finishingbot, .reporters.glambot, .reporters.cipherbot][] | .enrolled' "$A/.gitbot-fleet/enrolment.json" | paste -sd' ' -)" diff --git a/tests/fleet-report-back-test.sh b/tests/fleet-report-back-test.sh index fe0d0c05..6c035fb1 100755 --- a/tests/fleet-report-back-test.sh +++ b/tests/fleet-report-back-test.sh @@ -192,20 +192,13 @@ stub cipherbot '[ "$1 $2 $3" = "--format json scan" ] || { echo "bad args: $*" > echo "[]"' # 5. envelope shape ──────────────────────────────────────────────────────────── -check "envelope keys are exactly the spec's, sorted" "findings reason ref reporter status title" \ - "$(field "$r" 'keys | join(" ")')" +check "envelope keys are exactly the spec's, sorted" "adapter_version findings reason ref reporter status title tool_version" "$(field "$r" 'keys | join(" ")')" + check "the envelope is compact with one final LF" 1 "$(wc -l < "$r")" check "the fleet ref is recorded" deadbeef "$(field "$r" .ref)" +check "finding keys are exactly the spec's" "evidence_class file line message rule_id semantic_fingerprint severity" "$(field "$r" ' .findings[0] | keys | join(" ")')" check "reason is null when the member ran" null "$(field "$r" .reason)" -check "finding keys are exactly the spec's" "file line message rule_id severity" "$(field "$r" '.findings[0] | keys | join(" ")')" - -# 6. --plan ──────────────────────────────────────────────────────────────────── -plan=$(bash "$DRIVER" --plan --enrolment "$REPO/.gitbot-fleet/enrolment.json") -check "--plan lists only enrolled members" 7 "$(printf '%s\n' "$plan" | wc -l)" -check "--plan names the finishingbot crate and binary" "finishingbot finishingbot finishing-bot" "$(printf '%s\n' "$plan" | grep '^finishingbot')" -check "--plan gives echidnabot no crate: nothing is built for a member without a local mode" "echidnabot " "$(printf '%s\n' "$plan" | grep '^echidnabot')" -# 7. summary ─────────────────────────────────────────────────────────────────── check "summary has one row per member" 7 "$(grep -c '^| [a-z]' "$TMP/o1.md")" check "summary states the error reason" yes "$(grep -q '| echidnabot | not_run | 0 | no ECHIDNA' "$TMP/o1.md" && echo yes || echo no)" @@ -260,8 +253,9 @@ for alias in finishbot finishing-bot; do done plan=$(bash "$DRIVER" --plan --enrolment "" --member finishbot --member finishing-bot --member cipherbot) check "--plan maps aliases and cipherbot to their crates and binaries" \ - $'finishbot\tfinishingbot\tfinishing-bot\nfinishing-bot\tfinishingbot\tfinishing-bot\ncipherbot\tcipherbot\tcipherbot' "$plan" - + $'finishbot finishingbot finishing-bot +finishing-bot finishingbot finishing-bot +cipherbot cipherbot cipherbot' "$plan" stub rhodibot 'cat <