Skip to content

fix(engine): apply code-review findings for the integration and recorded-diff hardening - #44

Merged
erikreinert merged 5 commits into
fix/run-postmordemfrom
claude/code-review-ultra-1umx3w
Oct 23, 2026
Merged

erikreinert merged 5 commits into
fix/run-postmordemfrom
claude/code-review-ultra-1umx3w

Conversation

@erikreinert

@erikreinert erikreinert commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Fixes for 31 verified findings from a full review of #43. The five commits sit directly on top of fix/run-postmordem (82e5959), so this merges as a fast-forward. Each commit builds and vets on its own.

What changed

Hardened git runner (internal/engine/integrate_git.go, internal/config/gitctx.go)

  • Drop GIT_EXEC_PATH, GIT_TEMPLATE_DIR, GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM and the pathspec/attr-source variables from both scrubbed environments; resolve the git binary once per process instead of through the inherited PATH on every call. Tests now assert the variables that matter.
  • integrateGit (the one git write) is built on gitCommandHooksOff and adds -c commit.gpgsign=false, so a signing program named in the executor-writable repository config no longer runs during the conductor's pick.
  • --config-env support is probed once; a git older than 2.31 gets no hook flags instead of failing every command.
  • Hook-flag listing is memoized per directory, so each git read no longer forks a second git.
  • cherry-pick passes --keep-redundant-commits, so a chain whose first commit already landed by hand integrates instead of aborting.
  • core.quotePath, diff.noprefix and diff.mnemonicPrefix are pinned so diff headers keep the a/ b/ shape.
  • The eight sequencer/grafts/shallow paths are read with one rev-parse over one table.

Diff recording and elision (internal/engine/diff_elide.go, saga.go)

  • An oversize section is judged binary by probing the first 8000 bytes of both blobs (or the worktree file when the after side is unstored) for a NUL, so a binary changed below its header is capped instead of recorded whole into issue.diff and every packet.
  • The diff --git header is parsed with C-unquoting and a same-path split, so quoted, noprefix and ' b/'-containing paths still reach generated-file elision; an already-capped section reports the counts from its marker.

Recorded head and gate stages (recorded_head.go, saga.go, pregate_scratch.go)

  • --worktree is compared against the run's exec root after resolving symlinks, so a symlinked spelling of the shared checkout is not bound as a separate live worktree; the exec root is read once per completion.
  • A recorded-head read error is returned from the gate and diff stages instead of silently measuring the live worktree.
  • One scratch checkout per resume is shared across the completion gates (the diff stage keeps its own fresh tree): 6 worktree add/remove per completion becomes 2.
  • The saga patch-id helpers are projections of the integration-range ones; engine-reserved artifact kinds are named in one place.

step integrate / annotate (step_integrate.go, annotate_integration.go, CLI help)

  • planIntegration refuses an unanswerable carriage probe before any write, with the same refusal the annotation would give afterwards, so the shared branch never moves for a step that could not then be annotated.
  • AnnotateIntegration shape-checks the recorded writer chain before building a git command from it.
  • Step definitions are loaded once across the planning loop.
  • The annotate help, file header and --skip-integration-check help state the three accepted forms for an integrated sha and route everything else to the waiver.

Dispatch close and retry advisories (dispatch.go, dispatch_conditions.go, retry_eligible.go, unexpanded.go, hold.go, saga_detached.go, cli/run_status.go)

  • The --no-conditions waiver note is written inside the close transaction, so a close on a run that already rolled up to done no longer commits and then reports failure.
  • Every error other than no-open-dispatch is propagated from the open-dispatch read, so the unfiled-conditions check refuses instead of silently passing.
  • Condition voters are assembled from rows, so a name with a comma stays one voter.
  • A park is compared against its own activity_ms rather than the row's last write; rows.Err is checked on the dedupe read.
  • Steps and relations are loaded once and shared between the retry, unexpanded and held advisories; missing retry-eligible events are recorded in one transaction after one read.
  • The stranded-saga sweep keeps going when one step's lock cannot be taken; the hold attribution refusal names the right verb.

Comments, rendering, QA (step_comment.go, render/detail.go, scripts/qa/helpers.sh)

  • Control bytes and ANSI escape sequences are stripped from comment bodies on both render paths, so a body cannot forge a header at column 0.
  • ZWNJ, ZWJ, soft hyphen, word joiner and variation selectors are accepted in step comments when they follow a visible character (Persian, Hindi conjuncts, emoji sequences, text-presentation glyphs); they stay refused in blank-rendering positions.
  • The QA detached-saga wait is scoped to the suite's binary, fails loudly without pgrep or on timeout, and run_stdin gets the same hook.

Not applied

  • The dispatch-conditions time window (proposals.updated_at >= dispatch open): the inter-dispatch gap is the contract the feature's own test asserts, and closing it needs a seal timestamp the schema does not have. Left as a design question.

Notes

  • The annotate-side sha check is hex-only rather than strict 40-hex because shared test fixtures record abbreviated heads; it still rejects anything option-shaped.
  • The planning pass still runs the shared-checkout check per step; hoisting it needs a chain-only seam in the git runner.
  • Dropping GIT_CONFIG_GLOBAL from the scrubbed environment means engine git now reads the host's global config. The -c commit.gpgsign=false is what keeps the suite green on a host that sets commit.gpgsign, so those two changes should stay together.

Validation

gofmt, go build ./..., go vet ./..., staticcheck v0.7.0 clean. go test ./... passes on every package; internal/workflow passes with DOCKET_SWEEP_WORKFLOWS_DIR pointed at the CI corpus as the workflow does. scripts/qa.sh through section ZG: 1380/1380.

- Drop GIT_EXEC_PATH, GIT_TEMPLATE_DIR, GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM
  and the pathspec/attr-source variables from both scrubbed environments, and
  resolve the git binary once per process instead of through the inherited
  PATH on every call. The tests now assert the variables that matter.
- Build integrateGit on gitCommandHooksOff and add -c commit.gpgsign=false, so
  the engine's one git write no longer runs a signing program named in the
  executor-writable repository config.
- Probe --config-env support once and emit no hook flags on a git that
  predates it, instead of failing every command with an unknown option.
- Memoize the hook-flag listing per directory for the process lifetime so each
  git read no longer forks a second git.
- Pass --keep-redundant-commits so a chain whose first commit already landed
  by hand integrates instead of aborting on the empty pick.
- Pin core.quotePath, diff.noprefix and diff.mnemonicPrefix so diff headers
  keep the a/ b/ shape the parser expects.
- Read the eight sequencer and grafts paths with one rev-parse over one table.
…in step comments

- Drop C0/C1 controls and ANSI escape sequences from comment bodies on both
  the plain and the glamour path, so a body cannot forge a header at column 0
  through a carriage return or a cursor sequence; the forgery test now covers
  those bytes.
- Accept ZWNJ, ZWJ, soft hyphen, word joiner, variation selectors and
  ideographic variation selectors in a step comment when they follow a visible
  character, so Persian, Hindi conjuncts, emoji sequences and text-presentation
  glyphs post; they stay refused in blank-rendering positions.
- Scope the QA detached-saga wait to this suite's binary, fail loudly without
  pgrep or on timeout, and hook run_stdin the same way as run and run_env.
… read once

- Write the --no-conditions waiver note inside the close transaction so a
  close on a run that already rolled up to done no longer commits and then
  reports failure.
- Propagate every error other than no-open-dispatch from the open-dispatch
  read so the unfiled-conditions check refuses instead of silently passing.
- Assemble condition voters from rows rather than splitting a joined string,
  so a voter name holding a comma stays one voter.
- Compare a park against its own activity instant rather than the step row's
  last write, and check rows.Err on the retry-eligible dedupe read.
- Load a run's steps and relations once and share them between the retry,
  unexpanded and held advisories; record missing retry-eligible events in one
  transaction after one read.
- Keep sweeping stranded sagas when one step's lock cannot be taken, and name
  the right verb in the hold attribution refusal.
…ate writes

- planIntegration now refuses when the range probe cannot answer, with the
  same refusal the annotation would give after the pick, so the shared branch
  never moves for a step that could not then be annotated.
- AnnotateIntegration shape-checks the recorded writer chain before building
  a git command from it, as the integrate path already does.
- Load a run's step definitions once across the planning loop.
- State in the annotate help, the file header and the --skip-integration-check
  help which three forms an integrated sha is accepted in, and that any other
  hand resolution needs the per-close waiver.
…s gate stages

- Decide whether an oversize diff section is binary by probing the first 8000
  bytes of both blobs (or the worktree file when the after side is unstored)
  for a NUL, instead of only trusting a first hunk that starts at the top, so
  a binary changed below its header is capped rather than recorded whole.
- Parse the diff --git header with C-unquoting and a same-path split, so
  quoted, noprefix and ' b/'-containing paths still reach generated-file
  elision; take the counts of an already-capped section from its marker.
- Compare the --worktree against the run's exec root after resolving
  symlinks, so a symlinked spelling of the shared checkout is not bound as a
  separate live worktree; read the exec root once per completion.
- Return a recorded-head read error from the gate and diff stages instead of
  measuring the live worktree.
- Hold one scratch checkout per resume and share it across the completion
  gates; the diff stage keeps its own fresh tree.
- Make saga's patch-id helpers projections of the integration-range ones, and
  name the engine-reserved artifact kinds in one place.
@erikreinert
erikreinert added this pull request to stack #45 October 23, 2026 00:51
@erikreinert
erikreinert merged commit 83f19e5 into main Oct 23, 2026
8 checks passed
@erikreinert
erikreinert deleted the claude/code-review-ultra-1umx3w branch October 23, 2026 00:51
erikreinert added a commit that referenced this pull request Oct 23, 2026
…ded-diff hardening (#44)

* fix(engine): close the gaps in the hardened git runner

- Drop GIT_EXEC_PATH, GIT_TEMPLATE_DIR, GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM
  and the pathspec/attr-source variables from both scrubbed environments, and
  resolve the git binary once per process instead of through the inherited
  PATH on every call. The tests now assert the variables that matter.
- Build integrateGit on gitCommandHooksOff and add -c commit.gpgsign=false, so
  the engine's one git write no longer runs a signing program named in the
  executor-writable repository config.
- Probe --config-env support once and emit no hook flags on a git that
  predates it, instead of failing every command with an unknown option.
- Memoize the hook-flag listing per directory for the process lifetime so each
  git read no longer forks a second git.
- Pass --keep-redundant-commits so a chain whose first commit already landed
  by hand integrates instead of aborting on the empty pick.
- Pin core.quotePath, diff.noprefix and diff.mnemonicPrefix so diff headers
  keep the a/ b/ shape the parser expects.
- Read the eight sequencer and grafts paths with one rev-parse over one table.

* fix(render): strip control bytes from comment bodies; accept joiners in step comments

- Drop C0/C1 controls and ANSI escape sequences from comment bodies on both
  the plain and the glamour path, so a body cannot forge a header at column 0
  through a carriage return or a cursor sequence; the forgery test now covers
  those bytes.
- Accept ZWNJ, ZWJ, soft hyphen, word joiner, variation selectors and
  ideographic variation selectors in a step comment when they follow a visible
  character, so Persian, Hindi conjuncts, emoji sequences and text-presentation
  glyphs post; they stay refused in blank-rendering positions.
- Scope the QA detached-saga wait to this suite's binary, fail loudly without
  pgrep or on timeout, and hook run_stdin the same way as run and run_env.

* fix(engine): make dispatch close and retry advisories fail closed and read once

- Write the --no-conditions waiver note inside the close transaction so a
  close on a run that already rolled up to done no longer commits and then
  reports failure.
- Propagate every error other than no-open-dispatch from the open-dispatch
  read so the unfiled-conditions check refuses instead of silently passing.
- Assemble condition voters from rows rather than splitting a joined string,
  so a voter name holding a comma stays one voter.
- Compare a park against its own activity instant rather than the step row's
  last write, and check rows.Err on the retry-eligible dedupe read.
- Load a run's steps and relations once and share them between the retry,
  unexpanded and held advisories; record missing retry-eligible events in one
  transaction after one read.
- Keep sweeping stranded sagas when one step's lock cannot be taken, and name
  the right verb in the hold attribution refusal.

* fix(engine): refuse an unanswerable carriage probe before step integrate writes

- planIntegration now refuses when the range probe cannot answer, with the
  same refusal the annotation would give after the pick, so the shared branch
  never moves for a step that could not then be annotated.
- AnnotateIntegration shape-checks the recorded writer chain before building
  a git command from it, as the integrate path already does.
- Load a run's step definitions once across the planning loop.
- State in the annotate help, the file header and the --skip-integration-check
  help which three forms an integrated sha is accepted in, and that any other
  hand resolution needs the per-close waiver.

* fix(engine): cap binaries by their bytes and share one checkout across gate stages

- Decide whether an oversize diff section is binary by probing the first 8000
  bytes of both blobs (or the worktree file when the after side is unstored)
  for a NUL, instead of only trusting a first hunk that starts at the top, so
  a binary changed below its header is capped rather than recorded whole.
- Parse the diff --git header with C-unquoting and a same-path split, so
  quoted, noprefix and ' b/'-containing paths still reach generated-file
  elision; take the counts of an already-capped section from its marker.
- Compare the --worktree against the run's exec root after resolving
  symlinks, so a symlinked spelling of the shared checkout is not bound as a
  separate live worktree; read the exec root once per completion.
- Return a recorded-head read error from the gate and diff stages instead of
  measuring the live worktree.
- Hold one scratch checkout per resume and share it across the completion
  gates; the diff stage keeps its own fresh tree.
- Make saga's patch-id helpers projections of the integration-range ones, and
  name the engine-reserved artifact kinds in one place.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants