agent-harness / tasks /patches /TASK_S2_R001_016_source.patch
cuber12's picture
Publish agent harness research code and paper artifacts
d61821a verified
Raw
History Blame Contribute Delete
2.96 kB
diff --git a/common/buildlogger/build_logger.go b/common/buildlogger/build_logger.go
index a1c75e0b..0d9dc7fa 100644
--- a/common/buildlogger/build_logger.go
+++ b/common/buildlogger/build_logger.go
@@ -96,6 +96,71 @@ func (l *Logger) Stream(streamID int, streamType StreamType) io.WriteCloser {
return l.wrap(l.base, streamID, streamType)
}
+// StepRunnerStream returns a writer for output produced by step-runner. When
+// step-runner emits lines already pre-stamped in the runner's timestamper
+// format, the data flows straight through to the base trace; otherwise the
+// full wrap chain is applied. This is the single hook for any future
+// step-runner-specific stream behavior.
+func (l *Logger) StepRunnerStream(streamID int, streamType StreamType) io.WriteCloser {
+ if l.base == nil {
+ return internal.NewNopCloser(io.Discard)
+ }
+
+ return &stepRunnerStream{
+ passthrough: internal.NewSync(l.base),
+ buildWrapped: func() io.WriteCloser {
+ return l.wrap(l.base, streamID, streamType)
+ },
+ }
+}
+
+// stepRunnerStream picks between two writers on its first write. The runner's
+// timestamper emits a fixed-width header — YYYY-MM-DDTHH:MM:SS.UUUUUUZ<space>
+// — and isPreStamped validates that full shape so producers other than
+// step-runner that happen to put 'Z' at byte 26 don't trip the passthrough.
+//
+// The wrap chain (timestamper, masker, sanitizers, sync) is built lazily via
+// buildWrapped so streams that only see pre-stamped output never pay for it.
+// step-runner output is the dominant case, so the saving compounds across
+// streams.
+type stepRunnerStream struct {
+ once sync.Once
+ chosen io.WriteCloser
+ passthrough io.WriteCloser
+ buildWrapped func() io.WriteCloser
+}
+
+// isPreStamped reports whether p starts with a runner timestamper header
+// (YYYY-MM-DDTHH:MM:SS.UUUUUUZ<space>). Validating the full shape, not
+// just byte 26, hardens the detection against producers other than
+// step-runner that might happen to put 'Z' at byte 26.
+func isPreStamped(p []byte) bool {
+ if len(p) < 28 {
+ return false
+ }
+ return p[4] == '-' && p[7] == '-' && p[10] == 'T' &&
+ p[13] == ':' && p[16] == ':' && p[19] == '.' &&
+ p[26] == 'Z' && p[27] == ' '
+}
+
+func (s *stepRunnerStream) Write(p []byte) (int, error) {
+ s.once.Do(func() {
+ if isPreStamped(p) {
+ s.chosen = s.passthrough
+ } else {
+ s.chosen = s.buildWrapped()
+ }
+ })
+ return s.chosen.Write(p)
+}
+
+func (s *stepRunnerStream) Close() error {
+ // Close-without-write: nothing has been buffered by the wrap chain
+ // (it was never built), so the passthrough's Close is sufficient.
+ s.once.Do(func() { s.chosen = s.passthrough })
+ return s.chosen.Close()
+}
+
// wrap wraps the underlying writer with "filters". Order here somewhat
// matters, and the order they're instantiated in is the reverse order in which
// writes are processed, e.g. last added filter is the first to process data.