services/host_commands.run_command pumps each stderr line into JobLog
via on_stderr (job_worker.py:215) before it raises HostCommandError —
appending exc.stderr again as a single row produced a second copy of
the entire traceback truncated at JOB_LOG_LINE_MAX_CHARS (4096), which
was visible as the awkward duplicated/cut-off second block at the end
of failed install logs.
Split the existing `except subprocess.CalledProcessError` into two:
except HostCommandError: stderr already streamed — just record exit
code + last error summary on the job/server row. No log append.
except subprocess.CalledProcessError: catches raw CalledProcessErrors
raised outside host_commands (no pump ran), so still append stderr
to the log. Preserves the path test_called_process_error_fails_job
exercises.
New regression test asserts a HostCommandError with multi-line stderr
doesn't land as a single concatenated JobLog row.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>