fix(site-runtime): step-log review — trace-flag-gated ES step scope, shared-script Log, formatter guard

Task 5 code-review follow-ups:
- I1: ExternalSystemHelper gates its TraceStepScope on a new isTraced ctor arg
  (default false for direct construction), not on `_traceSink is not null` — a
  traced run without an inline collector still writes durable ScriptLog rows
  that must name their step.
- I2 (design §5): an inline shared script now SHARES its caller's ScriptLogger
  via the new `sharedLog` ctor param — one line cap, one anchor, one closing
  row. Consequence documented on the Log property: a shared script's lines
  carry the PARENT run's ExecutionId and land on the parent's ScriptRun node.
- M3: TraceCapturingLogger swallows a throwing formatter — most of what it
  captures is best-effort "audit write failed" warnings logged from inside a
  catch block, and a formatting exception must not escape that path.
- Tests: ApiCall step attribution, traced-without-collector, shared-script
  logger sharing, nested batch/wait scope attribution + unwind, throwing
  formatter; test (c) now also pins the anti-recursion property (EmitLog must
  log through the undecorated logger).

CompileSurfaceParityTests stays red until Task 7 mirrors Log on ScriptCompileSurface.
This commit is contained in:
Joseph Doherty
2026-09-09 12:10:17 -04:00
parent 488d955ba2
commit ee8a8e9d3d
4 changed files with 209 additions and 11 deletions
@@ -74,6 +74,22 @@ public sealed class TraceCapturingLogger : ILogger
_ => "error",
};
_sink.Runtime(name, formatter(state, exception), exception);
string message;
try
{
message = formatter(state, exception);
}
catch
{
// Deliberate swallow: formatting is the CALLER's code, and a great many of the entries
// captured here are the runtime's own best-effort "audit write failed" warnings logged
// from inside a catch block. A throwing formatter escaping this decorator would replace
// the original failure with a formatting exception on a path whose whole contract is
// that it never throws. The line is dropped; the inner logger already saw (or refused)
// it above, unchanged.
return;
}
_sink.Runtime(name, message, exception);
}
}