← Files ImagoARCHIVED FILE
scripts/validate_package.py
2.73 KB · Nov 9, 2026 · 00:48 UTC
#!/usr/bin/env python3
"""Offline package checks; not installed plugin or rendered image integration tests."""
import pathlib, json, re, sys, hashlib
from zipfile import ZipFile
R=pathlib.Path(__file__).resolve().parents[1]
errors=[];checks=0
def ck(cond,msg):
global checks
checks+=1
if not cond:errors.append(msg)
p=json.loads((R/'plugin.json').read_text())
c=json.loads((R/'.codex-plugin/plugin.json').read_text())
i=p['extensions']['com.openai']['interface']
ck(p['name']=='imago','name changed')
ck(p['version']=='0.2.0','bad version')
ck(p['author']['name']=='Tekris Labs','wrong author')
ck(c['interface']==i,'legacy interface mismatch')
ck(p['extensions']['com.openai']['onboardingSkill']=='./skills/imago/SKILL.md','bad onboarding skill')
ck(len(i['displayName'])<=30,'name too long')
ck(len(i['shortDescription'])<30,'subtitle >=30 characters')
ck(len(i['defaultPrompt'])==3,'must have 3 prompts')
for k in ['websiteURL','supportURL','privacyPolicyURL','termsOfServiceURL']:
ck(i[k].startswith('https://tekrislabs.com/'),f'URL missing: {k}')
for k in ['logo','composerIcon']:
ck((R/i[k]).exists(),f'missing asset: {k}')
ck(not (R/'mcp.json').exists(),'skills-only package has mcp.json')
ck(len(i['capabilities'])<=20,'too many capabilities')
for cap in i['capabilities']:ck(len(cap)<=120,'capability too long: '+cap)
for prompt in i['defaultPrompt']:ck(len(prompt)<=128,'prompt too long: '+prompt)
for f in (R/'skills').glob('*/SKILL.md'):
s=f.read_text(encoding='utf-8')
ck(bool(re.match(r'^---\nname: [a-z0-9-]+\ndescription: .+?\n---\n',s,re.S)),f'bad frontmatter {f}')
ck(len(s)>550,f'skill too short {f}')
ck('https://tekrislabs.com/' not in s, f'bad boilerplate leakage {f}')
for href in re.findall(r'`((?:\.\./)+[^`\s]+)`',s):
dest=(f.parent/href).resolve()
ck(dest.exists(),f'broken skill reference {f}: {href}')
for f in (R/'references').glob('*.md'):ck(f.stat().st_size>300, f'reference too short {f}')
for f in (R/'templates').glob('*'):ck(f.stat().st_size>80,f'template too small {f}')
b=json.loads((R/'benchmarks/cases.json').read_text())['cases']
ck(len(b)>=30,'insufficient benchmarks')
ck(len({c['id'] for c in b})==len(b),'duplicated benchmark IDs')
ck(sum(c['type']=='negative' for c in b)>=8,'insufficient negative benchmarks')
ck(all(c['status']=='not_executed' for c in b),'unexpected executed benchmark claim')
ck((R/'archive/original/SKILL.md').exists(),'original skill missing')
for f in (R/'archive/original/references').glob('*.md'):ck(f.stat().st_size>0,f'original reference empty {f}')
ck(not any('Krishna Sathvik' in f.read_text(errors='replace') for f in R.rglob('*.md')),'old developer identity remains in public markdown')
print(json.dumps({'passed':len(errors)==0,'checks':checks,'errors':errors},indent=2))
sys.exit(1 if errors else 0)
SHA-256: d2d473621a52390be94422338fe09f2de230185080affc75a1366e76ba8eb9df