A correction to the code - the hairpin was not starting at the correct place after a dynamic, but was starting at zero offset. Here's the fix:
(cons 0 (interval-start Y-ext)))))
->
(cons (interval-start X-ext) (interval-start Y-ext)))))
Andrew
== snip
% Open hairpin.
% By Nathan Ho and David Nalesnik.
#(define ((open-hairpin left-open right-open) grob)
(let* ((stencil (ly:hairpin::print grob))
(X-ext (ly:stencil-extent stencil X))
(Y-ext (ly:stencil-extent stencil Y))
(width (interval-length X-ext))
(height (interval-length Y-ext)))
(ly:stencil-translate
(ly:stencil-add
(ly:line-interface::line
grob
0 (* height (- 0.5 (* 0.5 left-open)))
width (* height (- 0.5 (* 0.5 right-open))))
(ly:line-interface::line
grob
0 (* height (+ 0.5 (* 0.5 left-open)))
width (* height (+ 0.5 (* 0.5 right-open)))))
(cons (interval-start X-ext) (interval-start Y-ext)))))