dev.developer.ana.cai。67545/33e76cf221f5e742a8990875122c3a1f20002eeff2de45eb2d782c335a4120ba;独立审核=HOLD/3/3,audit=272849/dcbf3e0fa5fad6d1e07fa2e9981f659949c908d6d08d9c3af930baa5dab6958e。write_stdin<=30000ms、parent-owned child timeout/termination、任意对象类型/来源矩阵、child-exit 后 parent raw observer。51135/7b31929fdc6f67c9aa78a11ea7685f97027c5bc2ac96510d906bdf586cf13d40;full=51206/6ea1f921913927009045a0c6168f2693de0d65d4f2ba0d33056bbafb38c9b052;ASCII、5 LF、0 CR/NUL、max line=23433。exec_command 恰好一次:shell=C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe、login=false、tty=false、workdir=E:\mb-ms-doc\project-info、yield_time_ms=2000、max_output_tokens=4096、cmd=<第 4 节 parent preimage>。session_id、output empty、exit absent 才调用一次非空 write_stdin:chars=<inherited exact transcript>、yield_time_ms=30000(tool cap)、max_output_tokens=4096。chars=''、yield_time_ms=10000、max_output_tokens=4096;该 poll 只观察 parent terminal,不写 stdin、不启动/重启 child。DELIVERY_OR_PARENT_LIVENESS_UNKNOWN/27,不再 poll/write/kill/retry;任何后续阶段保持禁止。process universe:tool-host parent PowerShell=exactly 1;parent 只可启动 frozen child PowerShell=0..1;candidate Python/csc/node/mysql/config-editor/query/database=0/0/0/0/0/0/false。成功总 external process=2。
BEGIN:<ID>、CREATED:<ID>、DONE:<ID>、STOP:<ASCII_CODE> 行;stderr 必须 0。ProcessStartInfo(UseShellExecute=false,redirect stdin/stdout/stderr,CreateNoWindow=true)启动 frozen child,写入 exact transcript 后 close stdin;stdout/stderr BaseStream 分离复制到内存。Kill() 恰好一次并 WaitForExit(5000);仍 live 即 CHILD_LIVENESS_UNKNOWN/27,parent 禁止 raw scan并直接终止。stream drain 每路最多 2000ms,任一未完成为 CHILD_STREAM_UNKNOWN/27。HasExited=true 后 parent 才执行 observer。observer 不启动第三进程:以 Get-Item -Force/FileInfo 识别 ABSENT/FILE/DIRECTORY/REPARSE/OTHER;FILE 且 non-reparse 时 FileStream(Open,Read,None) raw read、bytes/hash/profile。以下 fence(不含 fence、含恰好一个 final LF)是唯一 parent cmd。embedded here-string 是唯一 child source;parent 运行时以 UTF-16LE Base64 形成 child -EncodedCommand,并复核 child source bytes/hash(第 6 节固定)。
$ErrorActionPreference='Stop'
$ProgressPreference='SilentlyContinue'
$root='E:\mb-ms-doc\project-info'
$ids=@('Y01','Y02','Y03','Y04')
$paths=@('E:\mb-ms-doc\project-info\dev\ana-dev\ana_semi_preconsumption_v002.py','E:\mb-ms-doc\project-info\dev\ana-dev\test\test_ana_semi_preconsumption_v002.py','E:\mb-ms-doc\project-info\dev\ana-dev\test\ana_semi_preconsumption_vectors_v002.json','E:\mb-ms-doc\project-info\dev\ana-dev\test\run_ana_semi_preconsumption_validation_v002.py')
$sizes=@(17465,3359,4016,13037)
$hashes=@('89812a35ac352d6fd0887f0b67df85962070d637aba4962992b46e073dd4bcf6','1983df916d5b9553a885a949d2674d9f8a8e7b1a6c4c5989eadf48245d929cf0','86f563b43d934cb0828e395f557ded328ad2abcfb2c1ef7bdbc8a4c32c12cbca','244463c2a66910dd71564f148d5845672261dedc80a636e21e809712b691337e')
$childSource=@'
$ErrorActionPreference='Stop'
$ids=@('Y01','Y02','Y03','Y04')
$paths=@('E:\mb-ms-doc\project-info\dev\ana-dev\ana_semi_preconsumption_v002.py','E:\mb-ms-doc\project-info\dev\ana-dev\test\test_ana_semi_preconsumption_v002.py','E:\mb-ms-doc\project-info\dev\ana-dev\test\ana_semi_preconsumption_vectors_v002.json','E:\mb-ms-doc\project-info\dev\ana-dev\test\run_ana_semi_preconsumption_validation_v002.py')
$sizes=@(17465,3359,4016,13037)
$hashes=@('89812a35ac352d6fd0887f0b67df85962070d637aba4962992b46e073dd4bcf6','1983df916d5b9553a885a949d2674d9f8a8e7b1a6c4c5989eadf48245d929cf0','86f563b43d934cb0828e395f557ded328ad2abcfb2c1ef7bdbc8a4c32c12cbca','244463c2a66910dd71564f148d5845672261dedc80a636e21e809712b691337e')
function Sha([byte[]]$b){$s=[Security.Cryptography.SHA256]::Create();try{return([BitConverter]::ToString($s.ComputeHash($b))).Replace('-','').ToLowerInvariant()}finally{$s.Dispose()}}
function Fail([string]$c){[Console]::Out.WriteLine('STOP:'+$c);[Console]::Out.Flush();exit 27}
function Profile([int]$i,[byte[]]$b){if($b.Length-ne$sizes[$i]-or(Sha $b)-ne$hashes[$i]){Fail 'PAYLOAD_HASH'};if($b.Length-ge3-and$b[0]-eq239-and$b[1]-eq187-and$b[2]-eq191){Fail 'PAYLOAD_BOM'};if(@($b|Where-Object{$_-eq13-or$_-eq0}).Count-ne0){Fail 'PAYLOAD_CR_NUL'};$lf=@($b|Where-Object{$_-eq10}).Count;if($i-eq2){if($lf-ne0-or$b[-1]-ne125){Fail 'PAYLOAD_JCS_PROFILE'}}elseif($lf-lt1-or$b[-1]-ne10-or$b[-2]-eq10){Fail 'PAYLOAD_TEXT_PROFILE'}}
try{
$lines=@();for($i=0;$i-lt5;$i++){$v=[Console]::In.ReadLine();if($null-eq$v){Fail 'TRANSCRIPT_EOF'};$lines+=$v}
$payloadText=($lines[0..3]-join"`n")+"`n";$a=[Text.Encoding]::ASCII
$end=$lines[4]-split"`t",-1;if($end.Count-ne3-or$end[0]-ne'END'-or$end[1]-ne'4'-or$end[2]-ne(Sha $a.GetBytes($payloadText))){Fail 'TRANSCRIPT_END'}
$decoded=@();for($i=0;$i-lt4;$i++){$f=$lines[$i]-split"`t",-1;if($f.Count-ne5-or$f[0]-ne$ids[$i]-or$f[1]-cne$paths[$i]-or$f[2]-ne([string]$sizes[$i])-or$f[3]-ne$hashes[$i]){Fail 'TRANSCRIPT_FIELDS'};if($f[4]-cnotmatch'\A(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\z'){Fail 'TRANSCRIPT_BASE64'};try{$b=[Convert]::FromBase64String($f[4])}catch{Fail 'TRANSCRIPT_DECODE'};Profile $i $b;$decoded+=,$b}
for($i=0;$i-lt4;$i++){[Console]::Out.WriteLine('BEGIN:'+$ids[$i]);[Console]::Out.Flush();$fs=[IO.FileStream]::new($paths[$i],[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::None,4096,[IO.FileOptions]::WriteThrough);[Console]::Out.WriteLine('CREATED:'+$ids[$i]);[Console]::Out.Flush();try{$fs.Write($decoded[$i],0,$decoded[$i].Length);$fs.Flush($true)}finally{$fs.Dispose()};$rb=[IO.File]::ReadAllBytes($paths[$i]);Profile $i $rb;[Console]::Out.WriteLine('DONE:'+$ids[$i]);[Console]::Out.Flush()}
exit 0
}catch{Fail ('EXCEPTION_'+$_.Exception.GetType().Name.ToUpperInvariant())}
'@
function Sha([byte[]]$b){$s=[Security.Cryptography.SHA256]::Create();try{return([BitConverter]::ToString($s.ComputeHash($b))).Replace('-','').ToLowerInvariant()}finally{$s.Dispose()}}
function ReadExact([string]$p){$f=[IO.FileStream]::new($p,[IO.FileMode]::Open,[IO.FileAccess]::Read,[IO.FileShare]::None);try{$m=[IO.MemoryStream]::new();try{$f.CopyTo($m);return $m.ToArray()}finally{$m.Dispose()}}finally{$f.Dispose()}}
function Obj([int]$i,[hashtable]$progress){
$attempted=$(if($progress.ContainsKey('BEGIN:'+$ids[$i])){$true}elseif($progress.ContainsKey('PROGRESS_UNKNOWN')){$null}else{$false})
$createdSignal=$progress.ContainsKey('CREATED:'+$ids[$i]);$created=$(if($createdSignal){$true}elseif($progress.ContainsKey('PROGRESS_UNKNOWN')){$null}else{$false})
try{$x=Get-Item -LiteralPath $paths[$i] -Force -ErrorAction Stop}catch [Management.Automation.ItemNotFoundException]{return[ordered]@{id=$ids[$i];attempted=$attempted;created_by_attempt=$created;exists=$false;object_type='ABSENT';reparse=$false;bytes=$null;sha256=$null;validation='NOT_PRESENT'}}catch{return[ordered]@{id=$ids[$i];attempted=$attempted;created_by_attempt=$created;exists=$null;object_type='UNKNOWN';reparse=$null;bytes=$null;sha256=$null;validation='UNKNOWN'}}
if($attempted-eq$true-and-not$createdSignal){$created=$null}
$rp=(($x.Attributes-band[IO.FileAttributes]::ReparsePoint)-ne0);if($rp){return[ordered]@{id=$ids[$i];attempted=$attempted;created_by_attempt=$created;exists=$true;object_type='REPARSE';reparse=$true;bytes=$null;sha256=$null;validation='INVALID'}}
if($x.PSIsContainer){return[ordered]@{id=$ids[$i];attempted=$attempted;created_by_attempt=$created;exists=$true;object_type='DIRECTORY';reparse=$false;bytes=$null;sha256=$null;validation='INVALID'}}
try{$b=ReadExact $paths[$i];$valid=($b.Length-eq$sizes[$i]-and(Sha $b)-eq$hashes[$i]);return[ordered]@{id=$ids[$i];attempted=$attempted;created_by_attempt=$created;exists=$true;object_type='FILE';reparse=$false;bytes=$b.Length;sha256=(Sha $b);validation=$(if($valid){'VALID'}else{'INVALID'})}}catch{return[ordered]@{id=$ids[$i];attempted=$attempted;created_by_attempt=$created;exists=$true;object_type='FILE';reparse=$false;bytes=$null;sha256=$null;validation='UNKNOWN'}}
}
$parentExit=27;$terminal='PARENT_PRECHECK_STOP';$stop='UNINITIALIZED';$childStarted=$false;$childExited=$false;$childExit=$null;$timedOut=$false;$progress=@{}
try{
$lines=@();for($i=0;$i-lt5;$i++){$v=[Console]::In.ReadLine();if($null-eq$v){throw 'TRANSCRIPT_EOF'};$lines+=$v};$transcript=($lines-join"`n")+"`n"
$tb=[Text.Encoding]::ASCII.GetBytes($transcript);if($tb.Length-ne51206-or(Sha $tb)-ne'6ea1f921913927009045a0c6168f2693de0d65d4f2ba0d33056bbafb38c9b052'){throw 'TRANSCRIPT_HASH'}
foreach($d in @($root,(Join-Path $root 'dev'),(Join-Path $root 'dev\ana-dev'),(Join-Path $root 'dev\ana-dev\test'))){$di=[IO.DirectoryInfo]::new($d);if(-not$di.Exists-or($di.Attributes-band[IO.FileAttributes]::Directory)-eq0-or($di.Attributes-band[IO.FileAttributes]::ReparsePoint)-ne0){throw 'DIR_STATE'}}
foreach($p in $paths){try{Get-Item -LiteralPath $p -Force -ErrorAction Stop|Out-Null;throw 'TARGET_PREEXISTS'}catch [Management.Automation.ItemNotFoundException]{}}
$childBytes=[Text.UTF8Encoding]::new($false).GetBytes($childSource);if(Sha $childBytes-ne'e2723b03984cce9fc455461441a64fa3b057f54cec4d5e05f3af9acd739ac066'){throw 'CHILD_SOURCE_HASH'}
$enc=[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($childSource));$psi=[Diagnostics.ProcessStartInfo]::new();$psi.FileName='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe';$psi.Arguments='-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand '+$enc;$psi.UseShellExecute=$false;$psi.CreateNoWindow=$true;$psi.RedirectStandardInput=$true;$psi.RedirectStandardOutput=$true;$psi.RedirectStandardError=$true;$psi.StandardInputEncoding=[Text.Encoding]::ASCII
$p=[Diagnostics.Process]::new();$p.StartInfo=$psi;if(-not$p.Start()){throw 'CHILD_START_FALSE'};$childStarted=$true
$om=[IO.MemoryStream]::new();$em=[IO.MemoryStream]::new();$ot=$p.StandardOutput.BaseStream.CopyToAsync($om);$et=$p.StandardError.BaseStream.CopyToAsync($em);$p.StandardInput.Write($transcript);$p.StandardInput.Close()
if(-not$p.WaitForExit(10000)){$timedOut=$true;try{$p.Kill()}catch{};if(-not$p.WaitForExit(5000)){throw 'CHILD_LIVENESS_UNKNOWN'}};$childExited=$true;$childExit=$p.ExitCode
if(-not[Threading.Tasks.Task]::WaitAll(@($ot,$et),2000)){throw 'CHILD_STREAM_UNKNOWN'};$ob=$om.ToArray();$eb=$em.ToArray();if($eb.Length-ne0){throw 'CHILD_STDERR'}
try{$os=[Text.UTF8Encoding]::new($false,$true).GetString($ob)}catch{throw 'CHILD_STDOUT_UTF8'};$pls=@($os-split"`n"|Where-Object{$_-ne''});$expected=@('BEGIN:Y01','CREATED:Y01','DONE:Y01','BEGIN:Y02','CREATED:Y02','DONE:Y02','BEGIN:Y03','CREATED:Y03','DONE:Y03','BEGIN:Y04','CREATED:Y04','DONE:Y04');$pi=0;$seenStop=$false;foreach($q in $pls){if($q-cnotmatch'\A(?:(?:BEGIN|CREATED|DONE):Y0[1-4]|STOP:[A-Z0-9_]+)\z'){$progress['PROGRESS_UNKNOWN']=$true;throw 'CHILD_PROGRESS_SCHEMA'};if($q-like'STOP:*'){if($seenStop-or$q-ne$pls[-1]){$progress['PROGRESS_UNKNOWN']=$true;throw 'CHILD_PROGRESS_ORDER'};$seenStop=$true}else{if($seenStop-or$pi-ge$expected.Count-or$q-ne$expected[$pi]){$progress['PROGRESS_UNKNOWN']=$true;throw 'CHILD_PROGRESS_ORDER'};$pi++};if($progress.ContainsKey($q)){$progress['PROGRESS_UNKNOWN']=$true;throw 'CHILD_PROGRESS_DUPLICATE'};$progress[$q]=$true}
$stopLine=@($pls|Where-Object{$_-like'STOP:*'});if($timedOut){$terminal='CHILD_TIMEOUT_KILLED';$stop='CHILD_TIMEOUT';$parentExit=27}elseif($childExit-eq0){$terminal='SOURCE_FREEZE_COMPLETED_PENDING_STATIC_REVIEW';$stop=$null;$parentExit=0}else{$terminal='CHILD_FAIL_CLOSED';$stop=$(if($stopLine.Count-eq1){$stopLine[0].Substring(5)}else{'CHILD_EXIT_'+$childExit});$parentExit=27}
}catch{$msg=[string]$_.Exception.Message;$stop=$(if($msg-cmatch'\A[A-Z0-9_]+\z'){$msg}else{'PARENT_EXCEPTION_'+$_.Exception.GetType().Name.ToUpperInvariant()});$terminal=$(if($childStarted){'PARENT_OR_CHILD_UNCERTAIN_FAIL_CLOSED'}else{'PARENT_PRECHECK_STOP'});$parentExit=27}
finally{
$rows=@();if($childStarted-and-not$childExited){$progress['PROGRESS_UNKNOWN']=$true;for($i=0;$i-lt4;$i++){$rows+=[ordered]@{id=$ids[$i];attempted=$null;created_by_attempt=$null;exists=$null;object_type='UNKNOWN';reparse=$null;bytes=$null;sha256=$null;validation='UNKNOWN'}}}else{for($i=0;$i-lt4;$i++){$rows+=Obj $i $progress}}
$valid=@($rows|Where-Object{$_.validation-eq'VALID'}).Count;if($parentExit-eq0-and($valid-ne4-or-not$childExited-or$childExit-ne0)){$terminal='PARENT_OBSERVER_MISMATCH';$stop='FINAL_CROSS_FIELD';$parentExit=27}
$consumed=$(if(@($rows|Where-Object{$_.created_by_attempt-eq$true}).Count-gt0){$true}elseif(@($rows|Where-Object{$null-eq$_.created_by_attempt}).Count-gt0){$null}else{$false})
$existingCount=@($rows|Where-Object{$_.exists-eq$true}).Count
$o=[ordered]@{schema_id='ANA.SEMI.STAGE.S.PARENT.TERMINAL.V002';terminal_state=$terminal;stop_code=$stop;governance_exit_code=$parentExit;parent_process_count=1;child_process_count=$(if($childStarted){1}else{0});child_exited=$childExited;child_exit_code=$childExit;child_timed_out=$timedOut;authorization_consumed=$consumed;observed_existing_count=$existingCount;valid_count=$valid;rows=$rows}
$j=$o|ConvertTo-Json -Compress -Depth 6;[Console]::Out.WriteLine($j);exit $parentExit
}
top-level ordered fields:schema_id,terminal_state,stop_code,governance_exit_code,parent_process_count,child_process_count,child_exited,child_exit_code,child_timed_out,authorization_consumed,observed_existing_count,valid_count,rows。authorization_consumed=BOOL|null,actual child exit 与 governance exit 分离。
row ordered fields:id,attempted:BOOL|null,created_by_attempt:BOOL|null,exists:BOOL|null,object_type:ABSENT|FILE|DIRECTORY|REPARSE|UNKNOWN,reparse:BOOL|null,bytes:INT64|null,sha256:HEX64|null,validation:VALID|INVALID|NOT_PRESENT|UNKNOWN。
| actual after confirmed child exit | attempted | created_by_attempt | type | validation | consumption |
|---|---|---|---|---|---|
| precheck any object exists | false | false | actual FILE/DIRECTORY/REPARSE/OTHER | INVALID/UNKNOWN | false |
| no object, no BEGIN | false | false | ABSENT | NOT_PRESENT | false |
| BEGIN only, absent | true | false | ABSENT | NOT_PRESENT | false |
| BEGIN, object exists, no CREATED | true | null | actual type | VALID/INVALID/UNKNOWN | true iff later management attributes; native field remains false unless CREATED |
| CREATED, file exact | true | true | FILE | VALID | true |
| CREATED, file mismatch | true | true | FILE | INVALID | true |
| CREATED, unreadable | true | true | FILE | UNKNOWN | true |
| any directory/reparse | progress-derived | progress-derived/null | DIRECTORY/REPARSE | INVALID | created field governs |
| progress invalid/missing after child start | null | null | raw observed type | raw validation | UNKNOWN; final 27 |
Preexisting any-object 4-row closure never claims four ABSENT/count0;parent returns actual rows and child_process_count=0。Child live/kill-wait failure forbids observer scan; parent terminal fields child_exited=false and all attempt/origin/validation become UNKNOWN or pre-state, governance 27。
提交审核前 append-only 补齐:parent bytes/hash/parser;embedded child source bytes/hash/parser 并替换唯一 placeholder;child UTF-16LE Base64/argv bytes/hash;P01–P04 transcript inherited equality;parent/child output upper bounds;all precheck/BEGIN/CREATED/DONE/timeout/kill/stream/progress/object states literal terminal vectors。未补齐不得送审。
NOT_ISSUED/NOT_ISSUED/NOT_ISSUED。10984/e363433cae3efc3b06aa37237ab3f73f84f23b37253f24c9e511ce38a223f565;PS5.1 parser errors=0;CR/NUL/LF/final=0/0/59/0x0A。2793/e2723b03984cce9fc455461441a64fa3b057f54cec4d5e05f3af9acd739ac066;PS5.1 parser errors=0;UTF-8 final=0x7D(here-string runtime value不含 closing-delimiter 前 LF)。5586 bytes;EncodedCommand=7448 ASCII chars/0aa02969d579aa29ee80061abaacf65d08d97a238840ee7a69602dd3931970f6。ProcessStartInfo.Arguments=7523/928b5431929db0deccdf667f94a8970f505339f23908f8f6d8eb22d971e7d0e2;expected unquoted no-space executable command line=7581/cb829e5c59946110f08603873fd4b3be686f983b1be29de9947f65a7d5645670。51206/6ea1f921913927009045a0c6168f2693de0d65d4f2ba0d33056bbafb38c9b052;child stdin/parent stdin exact equality,parent/child 分别独立复核。<3800 chars+LF;所有动态 stop 先限制为 [A-Z0-9_]+ 或 exception type name;max_output_tokens=4096。child progress 最大 13 行、每行 <64 ASCII chars;stderr=0。row literal shorthand(展开时字段顺序固定为第 5 节):
N(ID)=attempted=false,created_by_attempt=false,exists=false,ABSENT,false,null,null,NOT_PRESENT。B(ID)=true,false,false,ABSENT,false,null,null,NOT_PRESENT(BEGIN、CreateNew 未成功)。U(ID)=null,null,null,UNKNOWN,null,null,null,UNKNOWN(child 未确认退出,禁止 scan)。V(ID)=true,true,true,FILE,false,<exact bytes>,<exact hash>,VALID。I(ID)=true,true,true,FILE,false,<observed bytes>,<observed hash>,INVALID。Q(ID)=true,true,true,FILE,false,null,null,UNKNOWN。R(ID)=attempted/created 依 progress,exists=true,REPARSE,true,null,null,INVALID。D(ID)=attempted/created 依 progress,exists=true,DIRECTORY,false,null,null,INVALID。X(ID,type)=attempted=true,created_by_attempt=null,exists=true,<raw type/reparse/bytes/hash/validation>(BEGIN 后 race,未见 CREATED)。terminal vectors:
| state | parent/child | progress | rows Y01/Y02/Y03/Y04 | consumed | actual child exit | governance |
|---|---|---|---|---|---|---|
| T00 tool parent start failure | 0/0 | none | external zero-state only | false | null | 27 |
| T01 transcript/dir precheck | 1/0 | none | N/N/N/N | false | null | 27 |
| T02 preexisting FILE/D/R at Yi | 1/0 | none | actual preexisting row at Yi;其余 N/actual | false | null | 27 |
| T03 child start false/exception | 1/0 | none | N/N/N/N | false | null | 27 |
| T04 child fails before BEGIN | 1/1 | STOP | N/N/N/N | false | 27/nonzero | 27 |
| T05 Yi BEGIN then absent/CreateNew fail | 1/1 | exact prefix+BEGIN | prior V;Yi=B;later N | false if i=1 else true | 27 | 27 |
| T06 Yi BEGIN then race object/no CREATED | 1/1 | exact prefix+BEGIN | prior V;Yi=X;later N/raw | null if i=1 else true | 27 | 27 |
| T07 Yi CREATED partial mismatch | 1/1 | prefix+CREATED | prior V;Yi=I;later N | true | 27 | 27 |
| T08 Yi CREATED unreadable | 1/1 | prefix+CREATED | prior V;Yi=Q;later N | true | 27 | 27 |
| T09 timeout + Kill + confirmed exit | 1/1 | valid prefix | child-exit 后 raw expansion N/B/V/I/Q/R/D/X | derived BOOL/null | nonzero | 27 |
| T10 child Kill/Wait liveness unknown | 1/1 | ignored | U/U/U/U;无 scan | null | null | 27 |
| T11 stream drain/stderr/UTF8 failure after exit | 1/1 | unknown | raw scan;attempt/created null where progress unsafe | BOOL/null | observed | 27 |
| T12 duplicate/out-of-order/invalid progress | 1/1 | invalid | raw scan;all origin nullable | BOOL/null | observed | 27 |
| T13 child exit0 but prefix/observer mismatch | 1/1 | not exact 12 | raw scan | derived | 0 | 27 |
| T14 success | 1/1 | exact BEGIN/CREATED/DONE×4 | V/V/V/V | true | 0 | 0 |
child_exited=false 永远使用 T10,不执行 Get-Item/read/hash;child_exited=true 才允许 parent observer。非空 write_stdin 只等 30000ms;正常 child 最坏 10000 timeout + 5000 kill-wait + 2000 drain + bounded observer <30000。单次 empty poll 只处理 tool 返回时尚未交付 parent terminal 的外层延迟,不改变 child/process/target 状态。
第 8 节 supersede 第 6 节“待补齐”;V029 无 placeholder,只允许独立计划审核。