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)
-
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.
-
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.
-
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.
-
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.
-
(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.
Summary
While following the
weave-git-mergeskill (branchweave-skill) to rebase abranch 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 wascommitted 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)
leynos/cuprum, rebasing a 24-commit branch ontoorigin/main.mainhad relocated symbols between modules (e.g._EventDetails/_StageObservation/_run_before_hooksmoved fromcuprum._pipeline_internalsto
cuprum._pipeline_types); the branch also had several "repair imports afterrebase" commits that reordered the same top-level import block.
git statusshowed a conflict incuprum/_subprocess_execution.py, yetweave summaryand the driver hadreported the earlier commits clean. Inspecting the index stages:
git show :3:(theirs) parsed fine.git show :2:(ours — the already-replayed earlier commits) failedast.parsewith aSyntaxError: it contained a truncatedfrom cuprum._subprocess_timeout import (with no body, a duplicated moduledocstring, and duplicated import lines.
(versus ~270 for each real side) with interleaved/duplicated blocks and an
inline
||||||| originalmarker glued to a line of code.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) didnot 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_typesimport relocation and produced parsing, test-passing fileswhere Weave had produced garbage:
weave setup --globalwrites themerge=weaverules into the user attributesfile (
~/.config/git/attributes), andcore.attributesFileis unset (so Gituses that default path). Overriding it to
/dev/nullfor the single commanddisables only that file — repo-tracked
.gitattributesrules 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] orweave setup --local[
.git/info/attributes] the lever differs; the general principle is to make themergeattributeunspecifiedfor the operation.)Proposed skill improvements (
skills/weave-git-merge)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 exit0onstructurally-broken output, so "run tests at the end" is not enough during a
multi-commit rebase where corruption is committed before tests ever run.
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 withcheck-attr), with the note that it disables only the user attributes fileand that the lever differs per setup scope.
Warn about the multi-commit rebase cascade. A silently-corrupted early
commit's output becomes the
ours(:2:) side of the next conflict, socorruption 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.
Sharpen the import claim in
references/behaviour.md. The "What resolvescleanly" 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.
(Cross-skill) Reference from the
rebaseskill. Rebases in an environmentwhere Weave is globally configured invoke it transparently. A one-line pointer
in
skills/rebase/SKILL.md— "if a conflict resolution looks garbled or aresolved 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-driverdefect: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 separateupstream 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 withmerge.zdiffAlgorithm/zdiff3configured, Linux.