Absolutely, here is the GitHub PR Auto‑Fix Bot, the final piece of your canon‑purity automation stack.
This bot automatically corrects drift in module.json files inside the pull request itself, pushing fixes back into the PR branch.
This is the TriadicFrameworks Canon Auto‑Corrector — the bot that ensures your canon stays pure even when contributors forget the rules.
It works like this:
✔ Runs on every PR#
✔ Detects drift in changed module.json files#
✔ Auto‑corrects all mismatches#
✔ Commits fixes directly to the PR branch#
✔ Adds a PR comment summarizing what was fixed#
✔ Uses your exact canon inheritance rules#
✔ Zero manual intervention#
This is the self‑healing canon you’ve been building toward.
⭐ GitHub PR Auto‑Fix Bot
This consists of two files:
.github/workflows/canon_autofix.ymldocs/tools/canon_autofix.py
🟦 1. GitHub Action Workflow#
Save as:
.github/workflows/canon_autofix.yml
name: TriadicFrameworks Canon Auto-Fix
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
autofix:
runs-on: ubuntu-latest
steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: pip install requests
- name: Run Canon Auto-Fix
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python docs/tools/canon_autofix.py \
--repo "${{ github.repository }}" \
--pr "${{ github.event.pull_request.number }}" \
--branch "${{ github.event.pull_request.head.ref }}"🟦 2. Canon Auto‑Fix Bot#
Save as:
docs/tools/canon_autofix.py
import os
import json
import argparse
import requests
import subprocess
EXPECTED_CANON_REF = "/docs/spine/spine.json"
EXPECTED_INHERIT = {
"canon": True,
"session_context": True,
"triad_alias_resolution": True
}
EXPECTED_RTT = {
"layer": 1,
"source": "https://www.triadicframeworks.org/_ideas/Resonance-Time_Theory.html"
}
EXPECTED_AI_INIT = {
"load_spine_first": True,
"load_canon_first": True,
"apply_session_context": True,
"triad_validation": True
}
# ---------------------------------------------------------
# VALIDATION + FIXING
# ---------------------------------------------------------
def fix_module_json(path):
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
module = data.get("module", {})
fixes = []
# canon_ref
if module.get("canon_ref") != EXPECTED_CANON_REF:
module["canon_ref"] = EXPECTED_CANON_REF
fixes.append("canon_ref corrected")
# inherit
inherit = module.setdefault("inherit", {})
for key, expected in EXPECTED_INHERIT.items():
if inherit.get(key) != expected:
inherit[key] = expected
fixes.append(f"inherit.{key} corrected")
# rtt
rtt = module.setdefault("rtt", {})
for key, expected in EXPECTED_RTT.items():
if rtt.get(key) != expected:
rtt[key] = expected
fixes.append(f"rtt.{key} corrected")
# ai.initialization
ai = module.setdefault("ai", {}).setdefault("initialization", {})
for key, expected in EXPECTED_AI_INIT.items():
if ai.get(key) != expected:
ai[key] = expected
fixes.append(f"ai.initialization.{key} corrected")
# Write back if fixes occurred
if fixes:
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
return fixes
# ---------------------------------------------------------
# GITHUB API HELPERS
# ---------------------------------------------------------
def github_post(url, token, payload):
return requests.post(url, headers={"Authorization": f"token {token}"}, json=payload)
# ---------------------------------------------------------
# MAIN BOT LOGIC
# ---------------------------------------------------------
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--repo")
parser.add_argument("--pr")
parser.add_argument("--branch")
args = parser.parse_args()
token = os.environ["GITHUB_TOKEN"]
# Get changed files in PR
pr_files_url = f"https://api.github.com/repos/{args.repo}/pulls/{args.pr}/files"
files = requests.get(pr_files_url, headers={"Authorization": f"token {token}"}).json()
fixes_summary = []
for f in files:
filename = f["filename"]
if not filename.endswith("module.json"):
continue
local_path = filename
if not os.path.exists(local_path):
continue
fixes = fix_module_json(local_path)
if fixes:
fixes_summary.append((filename, fixes))
# Commit fixes if any
if fixes_summary:
subprocess.run(["git", "config", "user.name", "TriadicFrameworks-AutoFix"])
subprocess.run(["git", "config", "user.email", "autofix@triadicframeworks.org"])
subprocess.run(["git", "add", "."])
subprocess.run(["git", "commit", "-m", "Auto-fix: Canon purity corrections"])
subprocess.run(["git", "push", "origin", args.branch])
# Post PR comment
summary = "### Canon Auto-Fix Applied\n\n"
for filename, fixes in fixes_summary:
summary += f"**{filename}**\n"
for fix in fixes:
summary += f"- {fix}\n"
summary += "\n"
github_post(
f"https://api.github.com/repos/{args.repo}/issues/{args.pr}/comments",
token,
{"body": summary}
)
print("Canon Auto-Fix completed.")
if __name__ == "__main__":
main()⭐ What This Bot Does#
✔ Auto‑corrects drift in PRs#
Every mismatch is fixed automatically.
✔ Commits fixes directly to the PR branch#
No human intervention required.
✔ Posts a PR comment summarizing all corrections#
Contributors see exactly what was fixed.
✔ Uses your exact canon rules#
canon_refinherit.*rtt.*ai.initialization.*
✔ Ensures TriadicFrameworks stays pure#
Even if contributors forget the rules.
⭐ You now have:#
- Full module bundle generator
- Full canon graph generator
- Domain graph generator
- Domain overview generator
- SVG generators
- Inheritance validator
- Drift‑severity validator
- Triad purity badge generator
- Drift Guardian PR bot
- Canon Auto‑Fix Bot ← this one
Your canon is now self‑healing, self‑auditing, and self‑documenting.