← Files Memory KeeperARCHIVED FILE
skills/maintaining-memory-keeper/tests/test_package_lint_self.py
4.5 KB · Oct 4, 2026 · 12:34 UTC
from __future__ import annotations
import os, shutil, subprocess, sys, tempfile, unittest, zipfile
from pathlib import Path
PLUGIN=Path(__file__).resolve().parents[3]
LINTER=PLUGIN/'skills/maintaining-memory-keeper/scripts/package_lint.py'
class PackageLintSelf(unittest.TestCase):
def test_source_tree_passes(self):
r=subprocess.run([sys.executable,str(LINTER),str(PLUGIN)],capture_output=True,text=True)
self.assertEqual(r.returncode,0,r.stdout+r.stderr)
self.assertIn('PASS',r.stdout)
def test_bad_zip_fails_cleanly(self):
with tempfile.TemporaryDirectory() as td:
bad=Path(td)/'broken.zip'
bad.write_bytes(b'not-a-zip')
r=subprocess.run([sys.executable,str(LINTER),str(bad)],capture_output=True,text=True)
self.assertNotEqual(r.returncode,0)
self.assertIn('FAIL',r.stdout)
self.assertNotIn('Traceback',r.stdout+r.stderr)
def test_skills_fallback_zip_is_supported(self):
with tempfile.TemporaryDirectory() as td:
stage=Path(td)/'stage'
shutil.copytree(PLUGIN/'skills',stage/'skills')
(stage/'README.md').write_text('Memory Keeper 0.5.0\nMEMORY_KEEPER_V4_2026-09-17\n')
zpath=Path(td)/'skills.zip'
with zipfile.ZipFile(zpath,'w') as zf:
for f in sorted(stage.rglob('*')):
if f.is_file(): zf.write(f,f.relative_to(stage).as_posix())
r=subprocess.run([sys.executable,str(LINTER),str(zpath)],capture_output=True,text=True)
self.assertEqual(r.returncode,0,r.stdout+r.stderr)
def test_stale_diagnostic_marker_is_rejected(self):
with tempfile.TemporaryDirectory() as td:
clone=Path(td)/'memory-keeper'
shutil.copytree(PLUGIN,clone)
router=clone/'skills/using-memory-keeper/SKILL.md'
fake='MEMORY_KEEPER_' + 'V99_1999-01-01'
router.write_text(router.read_text().replace('MEMORY_KEEPER_V4_2026-09-17',fake))
r=subprocess.run([sys.executable,str(LINTER),str(clone)],capture_output=True,text=True)
self.assertNotEqual(r.returncode,0)
self.assertIn('stale diagnostic marker',r.stdout)
def test_unsafe_zip_member_fails_cleanly(self):
with tempfile.TemporaryDirectory() as td:
bad=Path(td)/'unsafe.zip'
with zipfile.ZipFile(bad,'w') as zf:
zf.writestr('../escape.txt','nope')
r=subprocess.run([sys.executable,str(LINTER),str(bad)],capture_output=True,text=True)
self.assertNotEqual(r.returncode,0)
self.assertIn('unsafe ZIP member path',r.stdout)
self.assertNotIn('Traceback',r.stdout+r.stderr)
def test_release_runner_does_not_pollute_source(self):
if os.environ.get('MEMORY_KEEPER_RELEASE_RUNNER_ACTIVE') == '1':
self.skipTest('nested inside official release runner')
runner=PLUGIN/'skills/maintaining-memory-keeper/scripts/run_release_tests.py'
self.assertTrue(runner.is_file(), 'official release runner missing')
r=subprocess.run([sys.executable,str(runner),'--source',str(PLUGIN)],capture_output=True,text=True)
self.assertEqual(r.returncode,0,r.stdout+r.stderr)
caches=[p for p in PLUGIN.rglob('__pycache__') if p.is_dir()]
self.assertEqual(caches,[],f'runner polluted source: {caches}')
def test_openai_directory_metadata_violations_are_rejected(self):
with tempfile.TemporaryDirectory() as td:
clone=Path(td)/'memory-keeper'
shutil.copytree(PLUGIN,clone)
manifest_path=clone/'plugin.json'
manifest=__import__('json').loads(manifest_path.read_text())
manifest.pop('author',None)
iface=manifest['extensions']['com.openai']['interface']
iface.pop('developerName',None)
iface.pop('composerIcon',None)
iface.pop('logo',None)
iface['shortDescription']='x'*31
iface['defaultPrompt']=['one','two','three','four']
manifest_path.write_text(__import__('json').dumps(manifest,indent=2)+'\n')
r=subprocess.run([sys.executable,str(LINTER),str(clone)],capture_output=True,text=True)
self.assertNotEqual(r.returncode,0,r.stdout+r.stderr)
for phrase in ['author.name missing','developerName missing','shortDescription exceeds 30','defaultPrompt has more than 3','composerIcon missing','logo missing']:
self.assertIn(phrase,r.stdout)
if __name__=='__main__': unittest.main(verbosity=2)
SHA-256: a98d212d9276dd020136632a3ae93366ad5309532e93662b4b7a16930cd3d0a6