@@ -15,11 +15,6 @@ import {
1515} from "./store.ts" ;
1616import { isTerminalLifecycle } from "./types.ts" ;
1717
18- const SIDECAR_NEEDLES = [
19- "omp-fleet/src/sidecar.ts" ,
20- "@ericjuta/omp-fleet/src/sidecar.ts" ,
21- ] ;
22-
2318export interface LegacyLockMigrationDeps {
2419 readonly runner ?: CommandRunner ;
2520 readonly herdr ?: Pick < HerdrClient , "inspectPane" > ;
@@ -52,23 +47,30 @@ async function runCaptured(
5247 }
5348}
5449
55- function parsePidLines ( text : string ) : string [ ] {
50+ function parsePidOutput (
51+ text : string ,
52+ label : string ,
53+ requireBarePid : boolean ,
54+ ) : string [ ] {
5655 const pids : string [ ] = [ ] ;
5756 for ( const line of text . split ( "\n" ) ) {
58- const match = / ^ ( \d + ) \b / . exec ( line . trim ( ) ) ;
59- if ( match ?. [ 1 ] !== undefined ) pids . push ( match [ 1 ] ) ;
57+ if ( line . length === 0 ) continue ;
58+ const match = requireBarePid
59+ ? / ^ ( \d + ) $ / . exec ( line )
60+ : / ^ ( \d + ) (?: \s | $ ) / . exec ( line ) ;
61+ if ( match ?. [ 1 ] === undefined ) {
62+ throw new ProtocolStoreError (
63+ `legacy lock migration could not parse ${ label } ` ,
64+ ) ;
65+ }
66+ pids . push ( match [ 1 ] ) ;
6067 }
6168 return pids ;
6269}
6370
64- function isDocumentedNoMatch ( exitCode : number ) : boolean {
65- return exitCode === 1 ;
66- }
67-
6871function requireCleanProbe (
6972 result : CommandResult | undefined ,
7073 label : string ,
71- allowNoMatch : boolean ,
7274) : CommandResult {
7375 if ( result === undefined ) {
7476 throw new ProtocolStoreError (
@@ -85,22 +87,35 @@ function requireCleanProbe(
8587 `legacy lock migration ${ label } query was truncated` ,
8688 ) ;
8789 }
88- if ( result . stderr . trim ( ) . length > 0 ) {
90+ if ( result . stderr . length > 0 ) {
8991 throw new ProtocolStoreError (
9092 `legacy lock migration ${ label } query returned stderr` ,
9193 ) ;
9294 }
93- if (
94- result . exitCode !== 0 &&
95- ! ( allowNoMatch && isDocumentedNoMatch ( result . exitCode ) )
96- ) {
95+ if ( result . exitCode !== 0 && result . exitCode !== 1 ) {
9796 throw new ProtocolStoreError (
9897 `legacy lock migration could not query ${ label } ` ,
9998 ) ;
10099 }
101100 return result ;
102101}
103102
103+ function parseProbePids (
104+ result : CommandResult ,
105+ label : string ,
106+ requireBarePid : boolean ,
107+ ) : string [ ] {
108+ if ( result . exitCode === 1 ) {
109+ if ( result . stdout . length === 0 ) return [ ] ;
110+ } else if ( result . stdout . length > 0 ) {
111+ const pids = parsePidOutput ( result . stdout , label , requireBarePid ) ;
112+ if ( pids . length > 0 ) return pids ;
113+ }
114+ throw new ProtocolStoreError (
115+ `legacy lock migration ${ label } query returned contradictory output` ,
116+ ) ;
117+ }
118+
104119export async function collectLegacyLockLiveEvidence (
105120 storeRoot : string ,
106121 deps : LegacyLockMigrationDeps = { } ,
@@ -117,26 +132,14 @@ export async function collectLegacyLockLiveEvidence(
117132 const pgrep = requireCleanProbe (
118133 await runCaptured ( runner , "pgrep" , [ "-af" , "sidecar.ts" ] ) ,
119134 "sidecar PIDs" ,
120- true ,
121135 ) ;
122- const sidecarPids = pgrep . stdout
123- . split ( "\n" )
124- . map ( ( line ) => line . trim ( ) )
125- . filter (
126- ( line ) =>
127- line . length > 0 &&
128- SIDECAR_NEEDLES . some ( ( needle ) => line . includes ( needle ) ) ,
129- )
130- . flatMap ( ( line ) => parsePidLines ( line ) ) ;
136+ const sidecarPids = parseProbePids ( pgrep , "sidecar PIDs" , false ) ;
131137
132138 const lsof = requireCleanProbe (
133139 await runCaptured ( runner , "lsof" , [ "-t" , "--" , lockPath ] ) ,
134140 "lock holders" ,
135- true ,
136141 ) ;
137- const lockHolders = isDocumentedNoMatch ( lsof . exitCode )
138- ? [ ]
139- : parsePidLines ( lsof . stdout ) ;
142+ const lockHolders = parseProbePids ( lsof , "lock holder PIDs" , true ) ;
140143
141144 const store = new RunStore ( root ) ;
142145 const herdr = deps . herdr ?? new HerdrClient ( runner ) ;
@@ -153,9 +156,7 @@ export async function collectLegacyLockLiveEvidence(
153156 liveSupervisorPanes . push ( manifest . supervisorPaneId ) ;
154157 } catch ( error ) {
155158 const paneMissing =
156- ( error instanceof HerdrServerError &&
157- error . code === "pane_not_found" ) ||
158- ( error instanceof Error && / \b p a n e _ n o t _ f o u n d \b / . test ( error . message ) ) ;
159+ error instanceof HerdrServerError && error . code === "pane_not_found" ;
159160 if ( ! paneMissing ) {
160161 throw new ProtocolStoreError (
161162 "legacy lock migration could not inspect a recorded supervisor pane" ,
0 commit comments