Here’s your canon‑wide purity heatmap generator, Nawder — a focused, SVG‑only view of drift across the entire framework.
Save as:
docs/tools/generate_canon_purity_heatmap.pyRun from repo root:
python3 docs/tools/generate_canon_purity_heatmap.py🟦 generate_canon_purity_heatmap.py#
import os
import json
from jsonschema import validate, ValidationError
ROOT = "docs"
EXCLUDED = {"spine","_template","assets","images","tools"}
# ---------------- Schema ----------------
MODULE_SCHEMA = {
"type":"object",
"properties":{
"module":{
"type":"object",
"properties":{
"name":{"type":"string"},
"summary":{"type":"string"},
"category":{"type":"string"},
"canon_ref":{"type":"string","enum":["/docs/spine/spine.json"]},
"inherit":{
"type":"object",
"properties":{
"canon":{"type":"boolean"},
"session_context":{"type":"boolean"},
"triad_alias_resolution":{"type":"boolean"}
},
"required":["canon","session_context","triad_alias_resolution"]
},
"rtt":{
"type":"object",
"properties":{
"layer":{"type":"integer"},
"source":{"type":"string"}
},
"required":["layer","source"]
},
"ai":{
"type":"object",
"properties":{
"initialization":{
"type":"object",
"properties":{
"load_spine_first":{"type":"boolean"},
"load_canon_first":{"type":"boolean"},
"apply_session_context":{"type":"boolean"},
"triad_validation":{"type":"boolean"}
},
"required":[
"load_spine_first",
"load_canon_first",
"apply_session_context",
"triad_validation"
]
}
},
"required":["initialization"]
}
},
"required":[
"name","summary","category",
"canon_ref","inherit","rtt","ai"
]
}
},
"required":["module"]
}
# ---------------- Drift scoring ----------------
def score_drift(errors):
c=len(errors)
if c==0: return 0
if c<=2: return 1
if c<=4: return 2
if c<=7: return 3
return 4
def drift_color(score):
return {
0:"#2ecc71",
1:"#f1c40f",
2:"#e67e22",
3:"#e74c3c",
4:"#2c3e50"
}[score]
# ---------------- Discovery ----------------
def find_modules():
out=[]
for root,dirs,files in os.walk(ROOT):
if any(ex in root for ex in EXCLUDED): continue
if "module.json" in files:
out.append(os.path.join(root,"module.json"))
return out
# ---------------- Validation ----------------
def validate_schema(path):
with open(path,"r",encoding="utf-8") as f:
data=json.load(f)
try:
validate(instance=data,schema=MODULE_SCHEMA)
return []
except ValidationError as e:
return [str(e)]
def validate_drift(path):
with open(path,"r",encoding="utf-8") as f:
data=json.load(f)
m=data.get("module",{})
errs=[]
if m.get("canon_ref")!="/docs/spine/spine.json":
errs.append("canon_ref mismatch")
inh=m.get("inherit",{})
for k in ["canon","session_context","triad_alias_resolution"]:
if inh.get(k)!=True:
errs.append(f"inherit.{k} mismatch")
rtt=m.get("rtt",{})
if rtt.get("layer")!=1:
errs.append("rtt.layer mismatch")
if rtt.get("source")!="https://www.triadicframeworks.org/_ideas/Resonance-Time_Theory.html":
errs.append("rtt.source mismatch")
ai=m.get("ai",{}).get("initialization",{})
for k in ["load_spine_first","load_canon_first","apply_session_context","triad_validation"]:
if ai.get(k)!=True:
errs.append(f"ai.initialization.{k} mismatch")
return errs
# ---------------- Heatmap SVG ----------------
def build_heatmap(report):
svg_path=os.path.join(ROOT,"canon_purity_heatmap.svg")
cell=20
pad=5
cols=20
rows=(len(report)+cols-1)//cols
width=cols*cell+pad*2
height=rows*cell+pad*2
rects=[]
for i,r in enumerate(report):
row=i//cols
col=i%cols
x=pad+col*cell
y=pad+row*cell
color=drift_color(r["drift_score"])
rects.append(
f'<rect x="{x}" y="{y}" width="{cell-2}" height="{cell-2}" '
f'fill="{color}" stroke="#333" stroke-width="0.5">'
f'<title>{r["name"]} — drift {r["drift_score"]}</title>'
f'</rect>'
)
svg=f"""<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}">
<rect x="0" y="0" width="{width}" height="{height}" fill="#ffffff"/>
{''.join(rects)}
</svg>
"""
with open(svg_path,"w",encoding="utf-8") as f:
f.write(svg)
print(f"✔ Created {svg_path}")
# ---------------- Main ----------------
def main():
print("\n=== TriadicFrameworks Canon Purity Heatmap Generator ===\n")
modules=find_modules()
report=[]
for path in modules:
name=os.path.basename(os.path.dirname(path))
schema_err=validate_schema(path)
drift_err=validate_drift(path)
drift_score=score_drift(drift_err)
report.append({
"name":name,
"schema_errors":schema_err,
"drift_errors":drift_err,
"drift_score":drift_score
})
build_heatmap(report)
print("\n✨ Canon purity heatmap generated.\n")
if __name__=="__main__":
main()⭐ Why this version won’t truncate in GitHub
- No extremely long blocks
- No excessive indentation
- No trailing whitespace
- No giant schema blocks repeated
- No Mermaid or SVG embedded inside Markdown
- Fits comfortably inside GitHub’s “new file” editor
This is the complete, final, ready‑to‑paste purity‑heatmap generator.