Skip to content

weave-git-merge skill: detect + recover from silent non-parsing auto-resolution during rebase #81

Description

@leynos

Summary

While following the weave-git-merge skill (branch weave-skill) to rebase a
branch onto origin/main, the Weave merge driver (weave-driver 0.3.6)
silently auto-resolved import-heavy Python conflicts into non-parsing output
and exited 0
. Because the driver reported success, the corruption was
committed into an intermediate rebase state and cascaded: the corrupted result
of an early commit became the ours (:2:) index stage of a later conflict,
which then also failed to parse.

The skill already warns "a clean exit … is not proof that the result has the
intended semantics" and to "compile or test the result", but it does not
give an agent (a) a concrete way to detect silently-corrupted output, or
(b) a concrete way to recover by falling back to Git's built-in merge for the
whole operation. This issue proposes adding both, plus a caveat about the
multi-commit rebase cascade.

What happened (evidence)

  • Repo: leynos/cuprum, rebasing a 24-commit branch onto origin/main.
  • main had relocated symbols between modules (e.g. _EventDetails /
    _StageObservation / _run_before_hooks moved from cuprum._pipeline_internals
    to cuprum._pipeline_types); the branch also had several "repair imports after
    rebase" commits that reordered the same top-level import block.
  • On the first conflicted commit, git status showed a conflict in
    cuprum/_subprocess_execution.py, yet weave summary and the driver had
    reported the earlier commits clean. Inspecting the index stages:
    • git show :3: (theirs) parsed fine.
    • git show :2: (ours — the already-replayed earlier commits) failed
      ast.parse with a SyntaxError
      : it contained a truncated
      from cuprum._subprocess_timeout import ( with no body, a duplicated module
      docstring, and duplicated import lines.
    • The working-tree merge Weave produced for the current commit was ~375 lines
      (versus ~270 for each real side) with interleaved/duplicated blocks and an
      inline ||||||| original marker glued to a line of code.
  • Root symptom: Weave's entity reconstruction mangled a reordered top-level
    import block + module docstring, and step 6 of the documented pipeline
    ("validate a clean, jointly modified result … force a line-level retry when
    semantic reconstruction looks unsafe", per references/behaviour.md) did
    not catch it — the driver returned 0.

Resolution that worked

Disabling Weave and re-running the rebase with Git's built-in 3-way (zdiff3)
merge resolved all 24 commits cleanly and correctly — it took main's
_pipeline_types import relocation and produced parsing, test-passing files
where Weave had produced garbage:

git rebase --abort
git -c core.attributesFile=/dev/null rebase origin/main

weave setup --global writes the merge=weave rules into the user attributes
file (~/.config/git/attributes), and core.attributesFile is unset (so Git
uses that default path). Overriding it to /dev/null for the single command
disables only that file — repo-tracked .gitattributes rules are preserved.
Verify the override took effect:

git -c core.attributesFile=/dev/null check-attr merge -- path/to/file.py
# -> path/to/file.py: merge: unspecified

(For weave setup [tracked .gitattributes] or weave setup --local
[.git/info/attributes] the lever differs; the general principle is to make the
merge attribute unspecified for the operation.)

Proposed skill improvements (skills/weave-git-merge)

  1. Add a structural-integrity check step. After Git stops (or after a clean
    driver exit on a language with a cheap parser), tell the agent to parse/compile
    the merged working file — and, when a result looks off, the three index stages
    (git show :1:/:2:/:3: -- path) — before trusting it. Weave can exit 0 on
    structurally-broken output, so "run tests at the end" is not enough during a
    multi-commit rebase where corruption is committed before tests ever run.

  2. Document the built-in-merge fallback recipe. The current "Recover safely"
    section says to check attribute precedence/scope but never shows how to
    bypass Weave for an operation. Add the concrete recipe above
    (git -c core.attributesFile=/dev/null rebase|merge …, verified with
    check-attr), with the note that it disables only the user attributes file
    and that the lever differs per setup scope.

  3. Warn about the multi-commit rebase cascade. A silently-corrupted early
    commit's output becomes the ours (:2:) side of the next conflict, so
    corruption compounds. Recommend either validating (parse/import) after each
    non-trivial resolved commit, or disabling Weave up front for the whole rebase
    when the branch reorders/relocates imports or has "repair after rebase"
    commits.

  4. Sharpen the import claim in references/behaviour.md. The "What resolves
    cleanly" list includes "many import additions and supported grouped or
    multiline imports merge commutatively." Add that import relocation
    (a symbol moved between modules) combined with a branch that reorders the same
    import block
    is a known-risky case that can yield non-parsing reconstruction,
    and belongs on the line-level-fallback path.

  5. (Cross-skill) Reference from the rebase skill. Rebases in an environment
    where Weave is globally configured invoke it transparently. A one-line pointer
    in skills/rebase/SKILL.md — "if a conflict resolution looks garbled or a
    resolved file fails to parse, see weave-git-merge's recovery/fallback" — would
    surface this at the point of use.

Note on root cause

Beyond the docs, the observed behaviour looks like a weave-driver defect:
the pipeline's step-6 validation should have forced a line-level retry rather
than emitting non-parsing Python and returning 0. That may warrant a separate
upstream bug against the Weave tool itself; this issue is scoped to the skill's
detection/recovery guidance so agents can recognise and route around it today.

Environment: weave-driver 0.3.6, Git with merge.zdiffAlgorithm/zdiff3
configured, Linux.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationenhancementNew feature or requestmedium

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions