Skip to content

Commit 5570f82

Browse files
fix(ci): eradicate validate-eclexiaiser.py (Python ban — total) (#117)
## Summary `.github/scripts/validate-eclexiaiser.py` was the residual baseline-rot that surfaced after #114 (ReScript exemption) removed the fail-fast — the `governance / Language / package anti-pattern policy` step then reached its Python sub-check and flagged it. This was the blocker on #115. Per the canonical Hyperpolymath Language Policy, Python is wholly outlawed estate-wide with zero exemptions (only carve-out is SaltStack `_states`/`_modules`/`pillar`, which this file isn't). Replace with a POSIX-shell + awk validator doing the same three checks: 1. `[project]` section has a non-empty `name` 2. At least one `[[functions]]` table is declared 3. Each function table has a non-empty `name` and `source` The new script has no TOML-parser dependency. ## Test plan - [x] Local: happy path on current eclexiaiser.toml -> Valid: boj-server (1 function(s)) exit 0 - [x] Local: 3 failure modes each return exit 1 with the correct error message - [ ] CI: Validate eclexiaiser manifest step (Dogfood Gate) continues to pass - [ ] CI: governance / Language / package anti-pattern policy step now passes Refs hyperpolymath/standards#67 (Estate Language Policy). Refs hyperpolymath/standards#89 (was blocking the #92 allowlist work). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1e60f60 commit 5570f82

3 files changed

Lines changed: 101 additions & 40 deletions

File tree

.github/scripts/validate-eclexiaiser.py

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
4+
#
5+
# validate-eclexiaiser.sh — structural validation for ./eclexiaiser.toml.
6+
# Bash replacement for the prior Python implementation; Python is wholly
7+
# outlawed estate-wide (hyperpolymath/standards [Language Policy]) and the
8+
# governance / Language / package anti-pattern policy gate fails on any
9+
# in-tree `.py` file. This validator does the same three checks the Python
10+
# version did, purely via POSIX text tools — no TOML parser dependency.
11+
#
12+
# Checks:
13+
# 1. [project] section has a non-empty `name`
14+
# 2. At least one `[[functions]]` table is declared
15+
# 3. Each `[[functions]]` table has a non-empty `name` and `source`
16+
17+
set -euo pipefail
18+
19+
FILE="${1:-eclexiaiser.toml}"
20+
21+
if [ ! -f "$FILE" ]; then
22+
echo "ERROR: $FILE not found" >&2
23+
exit 1
24+
fi
25+
26+
# Strip comments + blank lines into a working buffer
27+
buf=$(sed -E 's/[[:space:]]*#.*$//' "$FILE" | grep -v '^[[:space:]]*$')
28+
29+
# Extract `name` under [project] — the value on the first `name = "..."` line
30+
# that appears AFTER [project] and BEFORE the next [section] header.
31+
project_name=$(
32+
printf '%s\n' "$buf" \
33+
| awk '
34+
/^\[project\][[:space:]]*$/ {in_project=1; next}
35+
/^\[/ {in_project=0}
36+
in_project && /^[[:space:]]*name[[:space:]]*=/ {
37+
sub(/^[^=]*=[[:space:]]*/, "")
38+
gsub(/^"|"$/, "")
39+
print
40+
exit
41+
}
42+
'
43+
)
44+
45+
if [ -z "$project_name" ]; then
46+
echo "ERROR: project.name is required" >&2
47+
exit 1
48+
fi
49+
50+
# Count [[functions]] tables and validate each one's name + source.
51+
# Each [[functions]] header opens a table that runs until the next header.
52+
errors=$(
53+
printf '%s\n' "$buf" \
54+
| awk '
55+
function flush( ok_name, ok_source) {
56+
if (!in_fn) return
57+
if (fn_name == "") print "ERROR: function name cannot be empty"
58+
if (fn_source == "") print "ERROR: function `" (fn_name ? fn_name : "<unnamed>") "` has no source path"
59+
}
60+
/^\[\[functions\]\][[:space:]]*$/ {
61+
flush()
62+
in_fn = 1
63+
fn_count++
64+
fn_name = ""
65+
fn_source = ""
66+
next
67+
}
68+
/^\[/ { flush(); in_fn = 0; next }
69+
in_fn && /^[[:space:]]*name[[:space:]]*=/ {
70+
v = $0
71+
sub(/^[^=]*=[[:space:]]*/, "", v)
72+
gsub(/^"|"$/, "", v)
73+
fn_name = v
74+
}
75+
in_fn && /^[[:space:]]*source[[:space:]]*=/ {
76+
v = $0
77+
sub(/^[^=]*=[[:space:]]*/, "", v)
78+
gsub(/^"|"$/, "", v)
79+
fn_source = v
80+
}
81+
END {
82+
flush()
83+
if (fn_count == 0) print "ERROR: at least one [[functions]] entry is required"
84+
printf "__COUNT__=%d\n", fn_count
85+
}
86+
'
87+
)
88+
89+
count=$(printf '%s\n' "$errors" | sed -n 's/^__COUNT__=//p')
90+
errs=$(printf '%s\n' "$errors" | grep -v '^__COUNT__=' || true)
91+
92+
if [ -n "$errs" ]; then
93+
printf '%s\n' "$errs" >&2
94+
exit 1
95+
fi
96+
97+
printf 'Valid: %s (%s function(s))\n' "$project_name" "$count"

.github/workflows/dogfood-gate.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,10 @@ jobs:
256256
257257
echo "has_manifest=true" >> "$GITHUB_OUTPUT"
258258
259-
# Validate TOML structure using Python 3.11+ tomllib.
260-
# Script lives in .github/scripts/ so the YAML block scalar and
261-
# Python's indentation rules don't conflict (see that file's header).
262-
python3 .github/scripts/validate-eclexiaiser.py || {
259+
# Validate TOML structure with a POSIX-shell + awk validator.
260+
# Python is wholly outlawed estate-wide (standards Language Policy)
261+
# and triggers the governance / package anti-pattern gate.
262+
.github/scripts/validate-eclexiaiser.sh ./eclexiaiser.toml || {
263263
echo "::error file=eclexiaiser.toml::Invalid eclexiaiser.toml — see step output for details"
264264
exit 1
265265
}

0 commit comments

Comments
 (0)