from pathlib import Path
import subprocess,sys
out=Path(__file__).resolve().parent
base=Path('/Users/yixiay/Documents/codexWorkSpace/issues/output/597084-review/impact-2026-11-04/source')
root=out.parent/'code';review=out.parent/'review-baseline';label='red' if '--baseline' in sys.argv else 'green'
java=out/'segment-wave-src';classes=out/('segment-wave-'+label);classes.mkdir(exist_ok=True)
def save(name,body):
 p=java/name;p.parent.mkdir(parents=True,exist_ok=True);p.write_text(body)
def stub(name,body):save(Path(name.replace('.','/')+'.java'),'package '+name.rsplit('.',1)[0]+';\n'+body)
stub('cn.jojo.cc.common.enums.DataBaseTypeEnum','public enum DataBaseTypeEnum {PROD, TEACHING, BOTH}')
stub('cn.jojo.cc.common.enums.english.SegmentStatusEnum','public enum SegmentStatusEnum {NORMAL(0), FAILED(1), INIT(2);private final int c;SegmentStatusEnum(int n){c=n;}public Integer getCode(){return c;}}')
stub('cn.jojo.cc.common.enums.english.SegmentContentTypeEnum','public enum SegmentContentTypeEnum {MATERIAL(1), ANSWER_AREA(2);private final int c;SegmentContentTypeEnum(int n){c=n;}public Integer getCode(){return c;}public static Integer contentTypeOfQuestionType(Integer t){return 1;}}')
stub('cn.jojo.cc.core.domain.question.library.QuestionDo','@lombok.Data public class QuestionDo {private Long id;private String questionKey;private Long updateTime;private Integer questionType;}')
stub('cn.jojo.cc.core.domain.english.QuestionSegmentDo','@lombok.Data public class QuestionSegmentDo {private Long id,questionId,questionRevision,updateTime,deleteTime,creatorId,operatorId;private Integer contentType,segmentStatus,retryCount;private String questionKey,sourceTextMd5,segments,lastError;}')
stub('cn.jojo.cc.core.bo.LoginUserBo','@lombok.Data public class LoginUserBo {private Long loginUserId;public LoginUserBo(Long id,String name){loginUserId=id;}}')
stub('cn.jojo.cc.biz.common.config.EnglishDictConfig','public class EnglishDictConfig {public boolean enabled=true;public boolean isSegmentExecutionEnabled(){return enabled;}public boolean isSegmentEnabled(){return enabled;}}')
stub('cn.jojo.cc.biz.model.bo.english.PhraseIndexSnapshot','public class PhraseIndexSnapshot {}')
stub('cn.jojo.cc.biz.cache.english.EnglishPhraseIndexCacheService','public class EnglishPhraseIndexCacheService {public cn.jojo.cc.biz.model.bo.english.PhraseIndexSnapshot readySnapshot(cn.jojo.cc.common.enums.DataBaseTypeEnum s){return new cn.jojo.cc.biz.model.bo.english.PhraseIndexSnapshot();}public cn.jojo.cc.biz.model.bo.english.PhraseIndexSnapshot freshSnapshotForWrite(cn.jojo.cc.common.enums.DataBaseTypeEnum s){return readySnapshot(s);}public cn.jojo.cc.biz.model.bo.english.PhraseMatch findLongestAt(cn.jojo.cc.biz.model.bo.english.PhraseIndexSnapshot s,String t,int n){return null;}}')
stub('cn.jojo.cc.biz.cache.english.EnglishWordCacheService','public class EnglishWordCacheService {public java.util.Map<String,Long> findIdsByNormalizeds(cn.jojo.cc.common.enums.DataBaseTypeEnum s,java.util.Set<String> t){return java.util.Map.of();}}')
stub('cn.jojo.cc.core.multidatasource.MultiDataSourceContextHolder','public class MultiDataSourceContextHolder {public static boolean isJYDatasource(){return true;}}')
stub('cn.jojo.cc.biz.service.english.segment.SegmentMatchIdResolver','public class SegmentMatchIdResolver {public cn.jojo.cc.common.dto.english.EnglishSegmentDto resolveIds(cn.jojo.cc.common.enums.DataBaseTypeEnum s,cn.jojo.cc.common.dto.english.EnglishSegmentDto d){return d;}}')
stub('cn.jojo.cc.core.service.english.QuestionSegmentCoreService',r'''public class QuestionSegmentCoreService {
 public cn.jojo.cc.core.domain.question.library.QuestionDo current;public java.util.List<cn.jojo.cc.core.domain.english.QuestionSegmentDo> rows=java.util.List.of();public int failures,locks;public boolean lockError;public java.util.List<String> events=new java.util.ArrayList<>();
 public cn.jojo.cc.core.domain.question.library.QuestionDo lockQuestion(Long id){events.add("lock");locks++;if(lockError)throw new IllegalStateException("derived table missing");return current;}
 public java.util.List<cn.jojo.cc.core.domain.english.QuestionSegmentDo> listByQuestionId(Long id){return rows;}
 public java.util.List<cn.jojo.cc.core.domain.english.QuestionSegmentDo> listByQuestionKeys(java.util.Collection<String> keys){return rows;}
 public boolean upsert(cn.jojo.cc.core.domain.english.QuestionSegmentDo d){return true;}
 public void softDeleteByDo(cn.jojo.cc.core.domain.english.QuestionSegmentDo d){}
 public void markFailedByQuestionId(Long id,Integer t,String k,String md5,Long rev,String err){events.add("failed");failures++;}
 public cn.jojo.cc.core.domain.english.QuestionSegmentDo reserveIdentity(Long id,String k,Integer t,Long r){return new cn.jojo.cc.core.domain.english.QuestionSegmentDo();}
 public void invalidateQuestion(Long id,Long rev){}
 public boolean insertSkeletonIfAbsent(cn.jojo.cc.core.domain.english.QuestionSegmentDo d){return true;}
}''')
stub('cn.jojo.cc.core.service.question.library.QuestionCoreService','public class QuestionCoreService {public cn.jojo.cc.core.domain.question.library.QuestionDo current;public java.util.List<cn.jojo.cc.core.domain.question.library.QuestionDo> listByKeys(java.util.Collection<String> keys){return java.util.List.of(current);}}')
stub('cn.jojo.cc.biz.service.component.AliyunRocketMQService','public class AliyunRocketMQService {public int sent;public void sendNAsync(String t,String m,String k){sent++;}}')
stub('cn.jojo.cc.common.enums.CcWorkerClusterTagEnum','public enum CcWorkerClusterTagEnum {ENGLISH_SEGMENT_SYNC_COMPUTE_EVENT;public String getValue(){return "compute";}}')
stub('cn.jojo.cc.biz.model.cache.FormAndDataCacheBo','@lombok.Data public class FormAndDataCacheBo{private Long businessId,segmentSourceFormDataId;private String outDataJson,segmentSourcePayloadHash,segmentSourceOutputHash;private com.alibaba.fastjson.JSON outDataJsonObj;}')
stub('cn.jojo.cc.biz.utils.UriToolsUtil','public class UriToolsUtil{public static String getPath(String s){return s;}}')
# The real engine, transaction bean, fingerprint service, delivery and hook are compiled below.
main=r'''import cn.jojo.cc.biz.service.english.segment.*;
import cn.jojo.cc.biz.common.config.*;import cn.jojo.cc.biz.cache.english.*;
import cn.jojo.cc.core.domain.question.library.*;import cn.jojo.cc.core.domain.english.*;
import cn.jojo.cc.core.service.english.*;import cn.jojo.cc.common.enums.*;
import org.springframework.transaction.*;import org.springframework.transaction.support.*;
import org.springframework.transaction.interceptor.*;import org.springframework.transaction.annotation.*;import org.springframework.aop.framework.*;
import java.util.*;
public class SegmentWaveProbe {
 static void set(Object o,String n,Object v){try{var f=o.getClass().getDeclaredField(n);f.setAccessible(true);f.set(o,v);}catch(Exception e){throw new RuntimeException(e);}}
 static boolean has(Object o,String n){try{o.getClass().getDeclaredField(n);return true;}catch(Exception e){return false;}}
 static class Manager implements PlatformTransactionManager {QuestionSegmentCoreService core;Manager(QuestionSegmentCoreService c){core=c;}public TransactionStatus getTransaction(TransactionDefinition d){core.events.add("begin");return new SimpleTransactionStatus(true);}public void commit(TransactionStatus s){core.events.add("commit");}public void rollback(TransactionStatus s){core.events.add("rollback");core.failures=0;}}
 @SuppressWarnings("unchecked") static <T>T proxy(T target,Manager m){var f=new ProxyFactory(target);f.setProxyTargetClass(true);f.addAdvice(new TransactionInterceptor(m,new AnnotationTransactionAttributeSource()));return (T)f.getProxy();}
 static class Extractor implements SegmentTextExtractor {boolean error;String body="old";public Map<Integer,List<String>> extractRichTextsByContentType(QuestionDo q){if(error)throw new IllegalStateException("bad body");return Map.of(1,List.of(body));}public String extractPlainText(String x){return x;}}
 @SuppressWarnings("unchecked") static Map<String,cn.jojo.cc.common.dto.english.EnglishSegmentDto> bound(EnglishSegmentDeliveryBizService service,Set<String> keys,Map<String,SelectedSegmentOutput> source){try{try{return (Map)service.getClass().getMethod("resolveByQuestionKeys",Set.class,Map.class).invoke(service,keys,source);}catch(NoSuchMethodException old){return service.resolveByQuestionKeys(keys);}}catch(Exception e){throw new RuntimeException(e);}}
 static int failed;static void check(boolean b,String n){System.out.println((b?"PASS ":"FAIL ")+n);if(!b)failed++;}
 public static void main(String[] args){
 var q=new QuestionDo();q.setId(1L);q.setQuestionKey("q1");q.setUpdateTime(1000L);q.setQuestionType(1);
 var core=new QuestionSegmentCoreService();core.current=q;var manager=new Manager(core);var extractor=new Extractor();extractor.error=true;
 var content=new SegmentContentSnapshotService();set(content,"segmentTextExtractor",extractor);
 var tx=new QuestionSegmentTxService();set(tx,"segments",core);set(tx,"content",content);var txProxy=proxy(tx,manager);
 var engine=new QuestionSegmentBizServiceImpl();var config=new EnglishDictConfig();
 set(engine,"questionSegmentCoreService",core);set(engine,"englishDictConfig",config);set(engine,"phraseIndexCacheService",new EnglishPhraseIndexCacheService());set(engine,"englishWordCacheService",new EnglishWordCacheService());
 if(has(engine,"segmentContentSnapshotService")){set(engine,"segmentContentSnapshotService",content);set(engine,"questionSegmentTxService",txProxy);}else{set(engine,"segmentTextExtractor",extractor);}
 var proxiedEngine=proxy(engine,manager);
 try{proxiedEngine.refreshOne(q,DataBaseTypeEnum.TEACHING,null);}catch(IllegalStateException expected){}
 System.out.println("TX events="+core.events+", committedFailures="+core.failures);
 check(core.failures==1 && core.events.indexOf("rollback")<core.events.lastIndexOf("failed"),"failed record commits after compute rollback and unlock");
 int locks=core.locks;config.enabled=false;proxiedEngine.refreshOne(q,DataBaseTypeEnum.TEACHING,null);check(core.locks==locks,"execution pause before DB lock and transaction");config.enabled=true;
 extractor.error=false;var row=new QuestionSegmentDo();row.setQuestionId(1L);row.setQuestionKey("q1");row.setContentType(1);row.setSegmentStatus(0);row.setQuestionRevision(1000L);row.setSourceTextMd5(content.fingerprint(content.readTexts(q)));row.setSegments("{\"matches\":[{\"text\":\"old\",\"type\":\"word\"}]}");core.rows=List.of(row);
 var delivery=new EnglishSegmentDeliveryBizService();set(delivery,"questionSegmentCoreService",core);set(delivery,"englishDictConfig",config);set(delivery,"segmentMatchIdResolver",new SegmentMatchIdResolver());
 if(has(delivery,"questionCoreService")){var questions=new cn.jojo.cc.core.service.question.library.QuestionCoreService();questions.current=q;set(delivery,"questionCoreService",questions);set(delivery,"segmentContentSnapshotService",content);}
 var json=com.alibaba.fastjson.JSON.parseObject(row.getSegments());String hash="form-v1:00000000000000000000000000000000",outputHash="output-v1:00000000000000000000000000000000";json.put("sourcePayloadHash",hash);json.put("sourceOutputPayloadHash",outputHash);json.put("sourceFormDataId",7L);json.put("sourceContentConfigId",8L);row.setSegments(json.toJSONString());
 var selected=new SelectedSegmentOutput(DataBaseTypeEnum.TEACHING,"/v2.json",new SegmentPayloadIdentity(hash,7L,8L,outputHash));
 check(delivery.resolveByQuestionKeys(Set.of("q1")).isEmpty(),"no actual response credential fails closed");
 check(bound(delivery,Set.of("q1"),Map.of("q1",selected)).containsKey("q1"),"same current output credential remains deliverable");
 var oldSelected=new SelectedSegmentOutput(DataBaseTypeEnum.TEACHING,"/v1.json",new SegmentPayloadIdentity("form-v1:11111111111111111111111111111111",7L,8L,outputHash));
 check(bound(delivery,Set.of("q1"),Map.of("q1",oldSelected)).isEmpty(),"actual selected old output rejects new stored sequence");
 var hook=new QuestionSegmentSaveHookService();var mq=new cn.jojo.cc.biz.service.component.AliyunRocketMQService();var state=new QuestionSegmentStateTxService();set(state,"segments",core);set(hook,"englishDictConfig",config);set(hook,"rocketMqProducerService",mq);set(hook,"applicationEventPublisher",(org.springframework.context.ApplicationEventPublisher)event -> {});set(hook,"questionSegmentStateTxService",proxy(state,manager));
 core.lockError=true;locks=core.locks;boolean hookOk=true;try{hook.hookSave(q,null);}catch(Exception e){hookOk=false;}
 check(hookOk&&core.locks==locks,"business save hook does not access derived table before commit");
 hookOk=true;try{hook.onSaveRequested(new cn.jojo.cc.biz.model.event.english.QuestionSegmentSaveRequestedEvent(hook,q,null));}catch(Exception e){hookOk=false;}
 check(hookOk&&mq.sent==1,"postcommit derived failure preserves main result and still sends compute");
 if(failed>0)System.exit(1);
 }}'''
save(Path('SegmentWaveProbe.java'),main)
files=list(java.rglob('*.java'))
actual=[
'application/src/main/java/cn/jojo/cc/biz/model/bo/english/PhraseMatch.java',
'application/src/main/java/cn/jojo/cc/biz/model/bo/english/SegmentSnapshot.java',
'api/rpc-api/src/main/java/cn/jojo/cc/common/dto/english/EnglishSegmentDto.java',
'application/src/main/java/cn/jojo/cc/biz/service/english/segment/QuestionSegmentBizService.java',
'application/src/main/java/cn/jojo/cc/biz/service/english/segment/SegmentResult.java',
'application/src/main/java/cn/jojo/cc/biz/service/english/segment/SegmentTextExtractor.java',
'application/src/main/java/cn/jojo/cc/biz/utils/MD5Util.java',
'application/src/main/java/cn/jojo/cc/biz/model/event/english/QuestionSegmentSaveRequestedEvent.java',
'application/src/main/java/cn/jojo/cc/biz/model/bo/english/EnglishSegmentSyncComputeMessage.java',
'common/src/main/java/cn/jojo/cc/common/utils/TextNormalizer.java']
files += [root/p if (root/p).exists() else base/p for p in actual]
changed=['application/src/main/java/cn/jojo/cc/biz/service/english/segment/'+n+'.java' for n in ['QuestionSegmentBizServiceImpl','EnglishSegmentDeliveryBizService','QuestionSegmentSaveHookService','QuestionSegmentStateTxService','QuestionSegmentTxService','SegmentContentSnapshotService','SegmentPayloadIdentity','SelectedSegmentOutput']]
for p in changed:
 files.append((review/p if (review/p).exists() else base/p if (base/p).exists() else root/p) if label=='red' else root/p)
files.append(root/'common/src/main/java/cn/jojo/cc/common/utils/EnglishWords.java')
m2=Path.home()/'.m2/repository';names=['org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar','org/apache/commons/commons-collections4/4.4/commons-collections4-4.4.jar','org/projectlombok/lombok/1.18.36/lombok-1.18.36.jar','org/slf4j/slf4j-api/2.0.16/slf4j-api-2.0.16.jar','com/alibaba/fastjson/1.2.83/fastjson-1.2.83.jar','jakarta/annotation/jakarta.annotation-api/2.1.1/jakarta.annotation-api-2.1.1.jar','io/swagger/core/v3/swagger-annotations-jakarta/2.2.25/swagger-annotations-jakarta-2.2.25.jar']
for n in ['spring-core','spring-aop','spring-beans','spring-context','spring-expression','spring-tx','spring-jcl']:names.append('org/springframework/'+n+'/6.2.0/'+n+'-6.2.0.jar')
names=[n.replace('spring-tx/6.2.0/spring-tx-6.2.0.jar','spring-tx/6.2.1/spring-tx-6.2.1.jar') for n in names]
cp=':'.join(str(m2/n) for n in names)
r=subprocess.run(['javac','-cp',cp,'-processorpath',str(m2/names[2]),'-d',str(classes),*map(str,files)],capture_output=True,text=True);(out/(label+'-segment-wave-compile.txt')).write_text(r.stdout+r.stderr);print('javac_exit',r.returncode)
if r.returncode:print(r.stderr);sys.exit(r.returncode)
r=subprocess.run(['java','-cp',str(classes)+':'+cp,'SegmentWaveProbe'],capture_output=True,text=True);(out/(label+'-segment-wave.txt')).write_text(r.stdout+r.stderr+'exit='+str(r.returncode)+'\n');print(r.stdout,r.stderr,'exit=',r.returncode);sys.exit(r.returncode)
