-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgithub.test.sh
More file actions
executable file
·174 lines (161 loc) · 6.05 KB
/
Copy pathgithub.test.sh
File metadata and controls
executable file
·174 lines (161 loc) · 6.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/env bash
# Contract test for the github plugin's durable invariants:
# - D4 zero-vendored-knowledge: no baked endpoints, no shipped scope tables, no prices
# - agnostic conformance: no publisher/org/tool assumptions in prose (plugin.json author is
# the sanctioned exception)
# - area-coverage oracle: reference/areas.md rows match the canonical Brief coverage list
# (fixture lives here, independent of the file it checks)
# - recipe non-hollow contract: every primary-tier recipe carries the six contract sections
# and a >=10-question audit checklist
set -uo pipefail
# mapfile (area oracle below) needs bash >= 4; on bash 3.x it fails silently under
# this set posture and the oracle would spuriously pass on empty arrays.
[[ "${BASH_VERSINFO[0]}" -ge 4 ]] || {
echo "SKIP: bash 4+ required (mapfile)" >&2
exit 0
}
PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
AREAS="$PLUGIN_DIR/reference/areas.md"
RECIPES_DIR="$PLUGIN_DIR/reference/recipes"
PASS=0
FAIL=0
fail() {
echo "FAIL: $*" >&2
FAIL=$((FAIL + 1))
}
ok() {
echo "ok: $*"
PASS=$((PASS + 1))
}
# sweep <ok-message> <failure-prefix> <grep arg>... -> pass when the grep finds
# nothing, fail with the hits listed under the prefix otherwise.
sweep() {
local ok_msg="$1" fail_msg="$2" hits
shift 2
hits=$(grep "$@" || true)
if [[ -z "$hits" ]]; then
ok "$ok_msg"
else
fail "$fail_msg"$'\n'"$hits"
fi
}
# --- D4 sweep: no baked endpoints anywhere in the plugin --------------------
# This file holds the very patterns it hunts, so the tree sweeps exclude it.
SELF_EXCLUDE=(--exclude="$(basename "${BASH_SOURCE[0]}")")
sweep "D4: no baked API endpoints" "D4 endpoint pattern found:" \
-rEn "${SELF_EXCLUDE[@]}" "api\.github\.com|/orgs/\{|/repos/\{|/enterprises/" "$PLUGIN_DIR"
# --- D4 sweep: no dollar prices anywhere in the plugin ----------------------
sweep "D4: no shipped prices" "D4 price pattern found:" \
-rEn "${SELF_EXCLUDE[@]}" '\$[0-9]' "$PLUGIN_DIR"
# --- D4 sweep: no scope names shipped as guidance ---------------------------
# Scope tokens in shipped prose (*.md) would be a vendored mechanics table; eval
# scenario prompts (*.json) may legitimately posit a scope by name.
sweep "D4: no scope names in shipped prose" "scope token in shipped prose:" \
-r -E -i -n "admin:(org|enterprise)|read:(org|user|packages)|write:(org|packages)|manage_billing|repo:status" \
"$PLUGIN_DIR" --include='*.md'
# --- agnostic conformance: no publisher/org/tool assumptions in prose -------
# plugin.json author metadata is the sanctioned exception (json excluded by the glob).
# Spelled out rather than routed through sweep: scripts/validate-plugin-contracts.mjs
# reads this literal grep to keep the regex aligned with
# scripts/org-agnosticism-tokens.txt class github.
hits=$(grep -riEn "melodic|medley|github-iac|pulumi" "$PLUGIN_DIR" --include='*.md' || true)
if [[ -z "$hits" ]]; then
ok "agnosticism: no publisher/org/tool assumptions in prose"
else
fail "agnosticism violation:"$'\n'"$hits"
fi
# --- area-coverage oracle ---------------------------------------------------
# Canonical area keys from the Brief coverage matrix. This fixture is the
# independent source the router rows are diffed against — update it only when
# the Brief's coverage list changes.
canonical_areas=(
rulesets
custom-properties
billing
security-model
codespaces
cloud-sandboxes
projects-and-issues
actions
webhooks
discussions
packages
pages
hosted-compute-networking
authentication-security
advanced-security
code-quality
deploy-keys
compliance
verified-domains
secrets-and-variables
github-apps
oauth-app-policy
personal-access-tokens
scheduled-reminders
archive-logs
deleted-repositories
developer-settings
)
if [[ ! -f "$AREAS" ]]; then
fail "missing $AREAS"
else
# Router rows are "| `key` | tier | ..." — extract the backticked key column.
# shellcheck disable=SC2016 # literal backtick/$ in the patterns, no expansion wanted
mapfile -t router_areas < <(grep -oE '^\| `[a-z0-9-]+`' "$AREAS" | sed 's/^| `//; s/`$//' | sort)
diff_out=$(diff <(printf '%s\n' "${canonical_areas[@]}" | sort) <(printf '%s\n' "${router_areas[@]}") || true)
if [[ -z "$diff_out" ]]; then
ok "area oracle: areas.md rows match the ${#canonical_areas[@]} canonical keys exactly"
else
fail "area oracle mismatch (canonical vs areas.md):"$'\n'"$diff_out"
fi
fi
# --- recipe non-hollow contract ---------------------------------------------
recipes=(billing.md security-posture.md rulesets-repo-drift.md actions-policy.md)
fixed_headings=(
"## Credential-and-gate preflight"
"## Audit-question checklist"
"## Drift comparison against declared conventions"
"## Dated caveats (re-verify live)"
"## Doc pointers"
)
for r in "${recipes[@]}"; do
f="$RECIPES_DIR/$r"
if [[ ! -f "$f" ]]; then
fail "missing recipe $r"
continue
fi
for h in "${fixed_headings[@]}"; do
if grep -qF "$h" "$f"; then
ok "$r carries '$h'"
else
fail "$r missing heading '$h'"
fi
done
# Sixth section is area-shaped: cost levers (billing) or posture heuristics.
if grep -qE "^## (Cost-control levers|Posture heuristics)$" "$f"; then
ok "$r carries a levers/heuristics section"
else
fail "$r missing '## Cost-control levers' or '## Posture heuristics'"
fi
# Checklist depth: >=10 numbered questions between the checklist heading and
# the next H2 (wrapped lines: count only list-starting lines).
qcount=$(awk '/^## Audit-question checklist$/{flag=1; next} /^## /{flag=0} flag && /^[0-9]+\./{n++} END{print n+0}' "$f")
if [[ "$qcount" -ge 10 ]]; then
ok "$r checklist has $qcount questions (>=10)"
else
fail "$r checklist has only $qcount numbered questions (<10)"
fi
done
# --- evals present for every judgment-bearing skill -------------------------
for s in audit advise setup; do
e="$PLUGIN_DIR/skills/$s/evals/evals.json"
if [[ -f "$e" ]] && grep -q '"skill_name"' "$e"; then
ok "evals present for $s"
else
fail "missing or malformed evals for $s ($e)"
fi
done
echo
echo "PASS=$PASS FAIL=$FAIL"
[[ "$FAIL" -eq 0 ]]