Skip to content

Commit c870f93

Browse files
Merge pull request #4 from hyperpolymath/feat/trope-build
fix(bots): neuter live mutating rhodibot → report-only audit mode (+directive, 4-mode setting) [WS-1]
2 parents 8ded785 + 0efe811 commit c870f93

2 files changed

Lines changed: 84 additions & 164 deletions

File tree

.github/workflows/rhodibot.yml

Lines changed: 58 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,189 +1,83 @@
11
# SPDX-License-Identifier: MPL-2.0
2-
# rhodibot.yml — Automated RSR compliance enforcement
2+
# rhodibot.yml — AUDIT MODE (report-only)
33
#
4-
# Reads root-hygiene rules and auto-fixes what it can:
5-
# - Delete banned files (AI.djot, duplicate CONTRIBUTING.adoc, stale snapshots)
6-
# - Rename misnamed files (AI.a2ml → 0-AI-MANIFEST.a2ml)
7-
# - Fix SPDX headers (AGPL → PMPL in dotfiles)
8-
# - Create missing required files (SECURITY.md, CONTRIBUTING.md)
9-
# - Report unfixable issues as PR comments
10-
#
11-
# Runs weekly and on Hypatia scan completion.
12-
13-
name: "⚙ Auto: Rhodibot RSR auto-fix"
4+
# rhodibot is temporarily in AUDIT MODE in this repo: it DETECTS RSR-compliance drift
5+
# and LOGS what it WOULD do, but performs NO mutations (no delete / rename / SPDX edit /
6+
# file create) and opens NO PR. Permissions are read-only. This neutralises the
7+
# directive-blind inline auto-fix (including the guardless SPDX sed) pending
8+
# convergence onto the deterministic gitbot-fleet engine. Tracked HIGH PRIORITY in
9+
# gitbot-fleet. Per-repo policy: .machine_readable/bot_directives/rhodibot.a2ml.
10+
11+
name: "⚙ Auto: Rhodibot RSR audit (report-only)"
1412
on:
1513
schedule:
1614
- cron: '0 6 * * 1' # Every Monday at 06:00 UTC
17-
workflow_dispatch: # Manual trigger
18-
workflow_run:
19-
workflows: ["Hypatia Neurosymbolic Analysis"]
20-
types: [completed]
15+
workflow_dispatch:
2116
permissions:
22-
contents: write
23-
pull-requests: write
17+
contents: read
2418
jobs:
25-
rhodibot:
19+
rhodibot-audit:
2620
runs-on: ubuntu-latest
27-
timeout-minutes: 15
21+
timeout-minutes: 10
2822
steps:
2923
- name: Checkout
3024
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
3125
with:
3226
fetch-depth: 1
33-
- name: Rhodibot — Scan and Fix
34-
id: fix
27+
- name: Rhodibot — AUDIT (detect + log; NO mutation, NO PR)
3528
run: |
3629
set -euo pipefail
37-
FIXES=""
30+
WOULD=""
3831
ISSUES=""
39-
CHANGED=false
32+
note() { WOULD="$WOULD\n- $1"; echo "AUDIT — would: $1"; }
33+
issue() { ISSUES="$ISSUES\n- $1"; echo "ISSUE: $1"; }
4034
41-
# --- 1. Delete banned files ---
42-
for pattern in "AI.djot" "NEXT_STEPS.md" "TODO.md" "NOTES.md" "TASKS.md"; do
43-
if [ -f "$pattern" ]; then
44-
rm "$pattern"
45-
FIXES="$FIXES\n- Deleted \`$pattern\` (superseded)"
46-
CHANGED=true
47-
fi
35+
# 1. Banned files
36+
for p in AI.djot NEXT_STEPS.md TODO.md NOTES.md TASKS.md; do
37+
if [ -f "$p" ]; then note "delete banned file \`$p\`"; fi
4838
done
49-
50-
# Delete stale snapshot files
39+
# 2. Stale snapshots
5140
for f in *-STATUS-*.md *-COMPLETION-*.md *-COMPLETE.md *-VERIFIED-*.md; do
52-
if [ -f "$f" ]; then
53-
rm "$f"
54-
FIXES="$FIXES\n- Deleted stale snapshot \`$f\`"
55-
CHANGED=true
56-
fi
41+
if [ -f "$f" ]; then note "delete stale snapshot \`$f\`"; fi
5742
done
58-
59-
# --- 2. Rename misnamed files ---
60-
if [ -f "AI.a2ml" ] && [ ! -f "0-AI-MANIFEST.a2ml" ]; then
61-
mv AI.a2ml 0-AI-MANIFEST.a2ml
62-
FIXES="$FIXES\n- Renamed \`AI.a2ml\` → \`0-AI-MANIFEST.a2ml\`"
63-
CHANGED=true
64-
fi
65-
66-
# --- 3. Delete duplicate format files ---
67-
if [ -f "CONTRIBUTING.md" ] && [ -f "CONTRIBUTING.adoc" ]; then
68-
rm CONTRIBUTING.adoc
69-
FIXES="$FIXES\n- Deleted duplicate \`CONTRIBUTING.adoc\` (keeping .md for GitHub)"
70-
CHANGED=true
71-
fi
72-
73-
if [ -f "README.md" ] && [ -f "README.adoc" ]; then
74-
# Only delete README.md if it's a stub (<5 lines)
75-
lines=$(wc -l < README.md)
76-
if [ "$lines" -lt 5 ]; then
77-
rm README.md
78-
FIXES="$FIXES\n- Deleted stub \`README.md\` (keeping .adoc)"
79-
CHANGED=true
80-
fi
81-
fi
82-
83-
# --- 4. Fix SPDX headers in dotfiles ---
84-
for dotfile in .gitignore .gitattributes .editorconfig; do
85-
if [ -f "$dotfile" ] && grep -q "AGPL-3.0" "$dotfile" 2>/dev/null; then
86-
sed -i 's/AGPL-3.0-or-later/MPL-2.0/g; s/AGPL-3.0/MPL-2.0/g' "$dotfile"
87-
FIXES="$FIXES\n- Fixed SPDX header in \`$dotfile\` (AGPL → PMPL)"
88-
CHANGED=true
43+
# 3. Misnamed
44+
if [ -f AI.a2ml ] && [ ! -f 0-AI-MANIFEST.a2ml ]; then note "rename \`AI.a2ml\` -> \`0-AI-MANIFEST.a2ml\`"; fi
45+
# 4. Duplicate format files
46+
if [ -f CONTRIBUTING.md ] && [ -f CONTRIBUTING.adoc ]; then note "remove duplicate \`CONTRIBUTING.adoc\`"; fi
47+
if [ -f README.md ] && [ -f README.adoc ] && [ "$(wc -l < README.md)" -lt 5 ]; then note "remove stub \`README.md\`"; fi
48+
# 5. SPDX drift in dotfiles — DETECT ONLY. Licence normalisation is the
49+
# deterministic engine's job (bot_directives/rhodibot.a2ml); never auto-edit here.
50+
for d in .gitignore .gitattributes .editorconfig; do
51+
if [ -f "$d" ] && grep -q "AGPL-3.0" "$d" 2>/dev/null; then
52+
note "flag SPDX drift in \`$d\` (AGPL-3.0 present) — DEFER to the deterministic engine; do NOT auto-edit"
8953
fi
9054
done
91-
92-
# --- 5. Create missing required files ---
93-
if [ ! -f "SECURITY.md" ]; then
94-
cat > SECURITY.md << 'SECEOF'
95-
<!-- SPDX-License-Identifier: MPL-2.0 -->
96-
# Security Policy
97-
98-
## Reporting a Vulnerability
99-
100-
**Email:** j.d.a.jewell@open.ac.uk
101-
102-
**Response timeline:**
103-
- Acknowledgement within 48 hours
104-
- Initial assessment within 7 days
105-
- Fix or mitigation within 90 days
106-
107-
**Safe harbour:** We will not pursue legal action against security researchers who follow responsible disclosure.
108-
SECEOF
109-
FIXES="$FIXES\n- Created missing \`SECURITY.md\`"
110-
CHANGED=true
111-
fi
112-
113-
if [ ! -f "CONTRIBUTING.md" ]; then
114-
cat > CONTRIBUTING.md << 'CONTEOF'
115-
<!-- SPDX-License-Identifier: MPL-2.0 -->
116-
# Contributing
117-
118-
1. Fork the repository
119-
2. Create a feature branch
120-
3. Ensure SPDX headers on all files
121-
4. Submit a pull request
122-
123-
**Author:** Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
124-
CONTEOF
125-
FIXES="$FIXES\n- Created missing \`CONTRIBUTING.md\`"
126-
CHANGED=true
127-
fi
128-
129-
# --- 6. Check for issues we can't auto-fix ---
130-
if [ ! -f "0-AI-MANIFEST.a2ml" ] && [ ! -f "AI.a2ml" ]; then
131-
ISSUES="$ISSUES\n- Missing AI manifest (0-AI-MANIFEST.a2ml)"
132-
fi
133-
134-
if [ ! -f "LICENSE" ] && [ ! -f "LICENSE.md" ] && [ ! -f "LICENSE.txt" ]; then
135-
ISSUES="$ISSUES\n- Missing LICENSE file"
136-
fi
137-
138-
if [ ! -f "README.adoc" ] && [ ! -f "README.md" ]; then
139-
ISSUES="$ISSUES\n- Missing README"
140-
fi
141-
142-
# Check for third-party fork (skip SPDX enforcement)
143-
if [ -f "LICENSE" ] && grep -q "multiple licenses\|LGPL\|Apache" LICENSE 2>/dev/null; then
144-
echo "FORK=true" >> $GITHUB_OUTPUT
145-
fi
146-
147-
# --- 7. Check dangerous patterns ---
148-
DANGEROUS=""
149-
for pattern in "believe_me" "assert_total" "Admitted" "sorry" "unsafeCoerce" "Obj.magic"; do
150-
count=$(grep -r "$pattern" --include='*.idr' --include='*.v' --include='*.lean' --include='*.hs' --include='*.ml' --include='*.res' . 2>/dev/null | grep -v node_modules | wc -l || echo 0)
151-
if [ "$count" -gt 0 ]; then
152-
DANGEROUS="$DANGEROUS\n- \`$pattern\`: $count occurrences"
153-
fi
55+
# 6. Missing required files
56+
if [ ! -f SECURITY.md ]; then note "create missing \`SECURITY.md\`"; fi
57+
if [ ! -f CONTRIBUTING.md ]; then note "create missing \`CONTRIBUTING.md\`"; fi
58+
# 7. Unfixable / report-only
59+
if [ ! -f 0-AI-MANIFEST.a2ml ] && [ ! -f AI.a2ml ]; then issue "missing AI manifest (0-AI-MANIFEST.a2ml)"; fi
60+
if [ ! -f LICENSE ] && [ ! -f LICENSE.md ] && [ ! -f LICENSE.txt ]; then issue "missing LICENSE file"; fi
61+
if [ ! -f README.adoc ] && [ ! -f README.md ]; then issue "missing README"; fi
62+
# 8. Dangerous patterns (soundness escape hatches)
63+
for pat in believe_me assert_total Admitted sorry unsafeCoerce Obj.magic; do
64+
c=$(grep -rl "$pat" --include='*.idr' --include='*.v' --include='*.lean' --include='*.hs' --include='*.ml' --include='*.res' . 2>/dev/null | grep -cv node_modules || true)
65+
if [ "${c:-0}" -gt 0 ]; then issue "dangerous pattern \`$pat\` in ${c} file(s)"; fi
15466
done
15567
156-
# Output results
157-
echo "CHANGED=$CHANGED" >> $GITHUB_OUTPUT
158-
{
159-
echo "FIXES<<EOF"
160-
echo -e "$FIXES"
161-
echo "EOF"
162-
} >> $GITHUB_OUTPUT
163-
{
164-
echo "ISSUES<<EOF"
165-
echo -e "$ISSUES"
166-
echo "EOF"
167-
} >> $GITHUB_OUTPUT
16868
{
169-
echo "DANGEROUS<<EOF"
170-
echo -e "$DANGEROUS"
171-
echo "EOF"
172-
} >> $GITHUB_OUTPUT
173-
- name: Create PR with fixes
174-
if: steps.fix.outputs.CHANGED == 'true'
175-
run: "git config user.name \"rhodibot\"\ngit config user.email \"rhodibot@hyperpolymath.dev\"\nBRANCH=\"rhodibot/rsr-compliance-$(date +%Y%m%d)\"\ngit checkout -b \"$BRANCH\"\ngit add -A\ngit commit -m \"fix(rhodibot): automated RSR compliance fixes\n\n${{ steps.fix.outputs.FIXES }}\n\nCo-Authored-By: rhodibot <rhodibot@hyperpolymath.dev>\"\n\ngit push origin \"$BRANCH\"\n\nBODY=\"## \U0001F916 Rhodibot — RSR Compliance Fixes\n\n### Changes Made\n${{ steps.fix.outputs.FIXES }}\n\"\n\nif [ -n \"${{ steps.fix.outputs.ISSUES }}\" ]; then\n BODY=\"$BODY\n### Issues Found (manual fix needed)\n${{ steps.fix.outputs.ISSUES }}\n\"\nfi\n\nif [ -n \"${{ steps.fix.outputs.DANGEROUS }}\" ]; then\n BODY=\"$BODY\n### ⚠️ Dangerous Patterns Detected\n${{ steps.fix.outputs.DANGEROUS }}\n\n_These bypass formal verification. See \\`proven\\` repo for alternatives._\n\"\nfi\n\ngh pr create \\\n --title \"\U0001F916 Rhodibot: RSR compliance fixes\" \\\n --body \"$BODY\" \\\n --base main \\\n --head \"$BRANCH\"\n"
176-
env:
177-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
178-
- name: Report (no changes needed)
179-
if: steps.fix.outputs.CHANGED != 'true'
180-
run: |
181-
echo "✅ Repository is RSR-compliant. No fixes needed."
182-
if [ -n "${{ steps.fix.outputs.ISSUES }}" ]; then
183-
echo "⚠️ Issues found (manual fix needed):"
184-
echo -e "${{ steps.fix.outputs.ISSUES }}"
185-
fi
186-
if [ -n "${{ steps.fix.outputs.DANGEROUS }}" ]; then
187-
echo "⚠️ Dangerous patterns:"
188-
echo -e "${{ steps.fix.outputs.DANGEROUS }}"
189-
fi
69+
echo "## 🔎 Rhodibot — AUDIT MODE (report-only; NO changes made)"
70+
echo ""
71+
if [ -n "$WOULD" ]; then
72+
echo "### Would auto-fix (SUPPRESSED in audit mode)"
73+
echo -e "$WOULD"
74+
else
75+
echo "_No auto-fixes would be applied._"
76+
fi
77+
echo ""
78+
if [ -n "$ISSUES" ]; then
79+
echo "### Issues (manual / deterministic engine)"
80+
echo -e "$ISSUES"
81+
fi
82+
} >> "$GITHUB_STEP_SUMMARY"
83+
echo "Rhodibot audit complete (report-only). No mutations, no PR."
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Media-Type: application/vnd.bot-directive+a2ml
4+
#
5+
# Per-repo directive for rhodibot — the DETERMINISTIC, symbolic RSR verifier
6+
# (gitbot-fleet/bots/rhodibot). rhodibot acts from hard-coded rules + these guards;
7+
# it is NOT a neural agent, so the no-automated-licence-edits rule (which scopes to
8+
# neural agents) does not forbid its bounded SPDX normalisation. Repo kind: software.
9+
#
10+
# OPERATING MODE (fleet-standard; ALL gitbot-fleet bots honour 'mode'):
11+
# active — perform actions: mutate the repo / open PRs.
12+
# audit — dry-run: do everything EXCEPT mutate; emit FULL forensic/debug output of
13+
# what it WOULD have done to a log/artefact (a pretend run).
14+
# passive — normal-mode reporting only: summarise repo state; no pretend-run forensics.
15+
# ignore — skip this repo entirely; do not even scan.
16+
17+
schema_version = "1.0"
18+
directive_type = "bot-directive"
19+
bot = "rhodibot"
20+
scope = "rsr-compliance"
21+
mode = "audit"
22+
enforcement = "full"
23+
repo-kind = "software"
24+
allow = ["metadata", "docs", "repo-structure checks", "policy validation", "SPDX normalisation to the repo's declared licences (code/config -> MPL-2.0; prose docs -> CC-BY-SA-4.0)"]
25+
deny = ["destructive edits without approval", "relicensing third-party / vendored / forked files", "any SPDX change whose correct licence cannot be deterministically determined (leave untouched)", "converting AGPL or other deliberate (non-drift) licences"]
26+
notes = "ACK: haec rhodibot directive loaded (mode=audit, FULL enforcement, software/language repo). While mode=audit rhodibot mutates nothing and only logs. When active: docs/metadata formatting + deterministic SPDX normalisation; never edit design/ or examples/ semantics without approval; leave undeterminable licences untouched."

0 commit comments

Comments
 (0)