from pathlib import Path import subprocess,os,signal,re,json,hashlib,time from datetime import datetime,timezone ROOT=Path(__file__).resolve().parents[4];P=Path(__file__).resolve().parent;O=P/'logs';O.mkdir(exist_ok=True) FILE='packages/harness/tests/claude-session.test.mjs';source=ROOT/FILE BASE='c16e943b90ef71ac96cfa5314bbea6040634d14d' old='realpathSync(workspace).replace(/[/.]/g, "-")';new='realpathSync(workspace).replace(/[^A-Za-z0-9]/g, "-")' original=source.read_bytes();assert original.decode().count(old)==1 fixed=original.decode().replace(old,new,1).encode() rows=[];temps=[] def stamp():return datetime.now(timezone.utc).isoformat() def verify(data): assert subprocess.check_output(['git','rev-parse','HEAD'],cwd=ROOT,text=True).strip()==BASE assert source.read_bytes()==data def run(label,template,data): verify(data);tmp=subprocess.check_output(['mktemp','-d',template],text=True).strip();temps.append(tmp) env=os.environ.copy();env.update(TMPDIR=tmp,DOCKER_HOST='unix:///mnt/storage/scratch/rocko-r304-dead.sock',NO_COLOR='1');env.pop('MOSAIC_GITEA_CREDENTIAL_FILE',None);env.pop('MOSAIC_LIVE_PROVIDER',None) args=['timeout','-k','10','180','node','--test','--test-reporter=tap',FILE];log=O/(label+'.tap');start=stamp();begin=time.monotonic() print('START',label,start,tmp,flush=True) with log.open('wb') as f: child=subprocess.Popen(args,cwd=ROOT,env=env,stdout=f,stderr=subprocess.STDOUT,start_new_session=True) try:rc=child.wait(timeout=195) except subprocess.TimeoutExpired: os.killpg(child.pid,signal.SIGKILL);child.wait();rc=124 finally: try:os.killpg(child.pid,signal.SIGTERM) except ProcessLookupError:pass text=log.read_text(errors='replace');counts={k:int(m[-1]) if (m:=re.findall(r'^# '+k+r' (\d+)\s*$',text,re.M)) else None for k in ['tests','pass','fail','cancelled','skipped']} row=dict(label=label,start=start,end=stamp(),seconds=round(time.monotonic()-begin,3),exit=rc,counts=counts,tmpdir=tmp,head=BASE,testSha256=hashlib.sha256(data).hexdigest(),skips=[x for x in text.splitlines() if re.search(r'^skip\b|# SKIP\b',x,re.I)],log=str(log.relative_to(ROOT))) rows.append(row) with (P/'results.jsonl').open('a') as f:f.write(json.dumps(row)+'\n') print('END',json.dumps(row),flush=True) assert rc not in [124,137,-9] and 'SyntaxError:' not in text,'invalid run '+label verify(data);return row,text def red(label,template,data): r,t=run(label,template,data) assert r['exit']!=0 and r['counts']['tests']==10 and r['counts']['pass']==9 and r['counts']['fail']==1 and r['counts']['cancelled']==0 and r['counts']['skipped']==0,'unexpected red counts '+label names=re.findall(r'^not ok \d+ - (.*)$',t,re.M) assert len(names)==1 and "CLAUDE.md files and auto-memory" in names[0] and ':298:10' in t and 'ERR_ASSERTION' in t and 'MARKER-MEMORY' in t,'unexpected red '+label def green(label,template,data): r,t=run(label,template,data) assert r['exit']==0 and r['counts']['tests']==10 and r['counts']['pass']==10 and r['counts']['fail']==0 and r['counts']['cancelled']==0 and r['counts']['skipped']==0,'unexpected mapping/refusal '+label try: red('baseline-underscore','/mnt/storage/scratch/tmp/rk304_XXXXXX',original) green('baseline-hyphen','/mnt/storage/scratch/tmp/rk304-XXXXXX',original) # Both installed-CLI probes now confirm the approved mapping before editing. source.write_bytes(fixed) green('fixed-mktemp','/mnt/storage/scratch/tmp/rk304XXXXXX',fixed) green('fixed-underscore','/mnt/storage/scratch/tmp/rk304_XXXXXX',fixed) green('fixed-space','/mnt/storage/scratch/tmp/rk304 XXXXXX',fixed) source.write_bytes(original) try:red('M1-old-regex','/mnt/storage/scratch/tmp/rk304_XXXXXX',original) finally:source.write_bytes(fixed) verify(fixed);print('BUILD_GREEN',stamp(),flush=True) finally: found=[] for proc in Path('/proc').glob('[0-9]*'): try: name=(proc/'comm').read_text().strip();cwd=str((proc/'cwd').resolve()) if any(x in name for x in ['node','chrom','claude']) and any(cwd==r or cwd.startswith(r+'/') for r in [str(ROOT),*temps]):found.append(dict(pid=int(proc.name),name=name,cwd=cwd)) except (FileNotFoundError,PermissionError,ProcessLookupError):pass (P/'cwd-sweep.json').write_text(json.dumps(found,indent=2)+'\n');print('CWD_SWEEP',found,flush=True)