Files in UD/DU/binary/etc. conflict states have no <<<<<<< markers in
the working tree. My earlier simplification that removed the
`git checkout --conflict=diff3` pre-check caused mergiraf to run on
them: it would exit 0 (nothing to solve), after which the unconditional
`git add` silently staged our side as resolved, losing the signal that
upstream deleted the file (or that we deleted what upstream modified).
Guard runMergiraf by inspecting the file before calling mergiraf: if
there are no conflict markers, skip the file entirely so it falls
through to manual review. Surface a skipped-count line in the normal
log output so the operator can see how many non-textual conflicts were
left alone.
Pass merge.conflictStyle=zdiff3 on the git merge invocation so every
conflicted file gets base-aware (|||||||) markers from the start, not
just the ones runMergiraf happens to touch. Benefits:
- Mergiraf always has a base section to work from, so its structural
heuristics apply uniformly.
- Remaining manual conflicts show both sides relative to the common
ancestor, which is dramatically easier to resolve than a 2-way marker.
Since the working tree already carries diff3 markers after the merge,
drop the per-file `git checkout --conflict=diff3` in runMergiraf.
mergiraf defaults to writing a .orig sibling file for every file it
touches. Pass --keep-backup=false so the merge script doesn't leave a
pile of .orig files across the working tree after running.
mergiraf exit 2 means it reduced conflicts but didn't fully close them.
Previously we bailed on any non-zero exit, throwing away the useful
partial reduction in the working tree. Now we always read the file after
mergiraf runs: if no conflict markers remain we stage, if markers remain
we keep the reduced content in the working tree for manual review but
leave the file unstaged so nothing half-resolved is auto-committed. Also
clean up the debug wording and surface a partial-resolution count in the
normal log output.
Previously git add and mergiraf solve could bubble up exit 128 (e.g. on
files missing the base version) and abort the entire merge. Wrap every
shell call in .nothrow() and skip to the next transform pass on failure.
Invokes `mergiraf solve` (syntax-aware git merge tool) on each conflicted
file before the kilocode-specific transform cascade, re-materializing the
file with diff3 markers first so mergiraf can reconstruct the base
revision. This auto-resolves the common pattern of neighbouring import
additions around kilocode_change markers plus most JSON/YAML/TOML and
other structural conflicts, leaving the existing transforms to handle
only what's genuinely ambiguous.
mergiraf is required at startup; if missing the script aborts early with
install instructions (brew / cargo / nix) rather than failing mid-merge.
The skip list in script/upstream/utils/config.ts matched .github/VOUCHED.md,
but upstream actually ships .github/VOUCHED.td (typo extension), so the file
fell through to manual resolution every merge. Broaden the pattern to
.github/VOUCHED.* so both variants are handled.
Also make skip-files removeFile report the real git rm stderr on failure
and retry once. Transient index contention silently flipped a file to
not-found in a recent run with no signal about why — now we'll see the
error and shake off intermittent lock failures automatically.
Transforms feed git-reported repo-relative paths into Bun.file() and
Glob.scan(), both of which resolve against cwd. Running the script from
script/upstream/ (as the README suggests) silently broke every file
lookup, causing pre-merge transforms to return zero results and i18n
auto-resolve to crash with ENOENT.
Uses 'git merge-base --is-ancestor' per tag (parallelized) to mark
upstream versions reachable from HEAD with a '✓ merged' annotation.
Kilo's own package version no longer tracks upstream, so semver
comparison isn't reliable; the ancestor check is the source of truth
and handles non-linear merge history correctly.
The catalog: protocol only resolves when the package is part of the root
workspace. script/upstream is intentionally decoupled from the monorepo
so it can run during upstream merges (when the workspace may be in a
half-broken state), which means 'cd script/upstream && bun install'
failed with 'failed to resolve catalog:'. Pin to the version currently
in the root catalog.
Previously the check trimmed each separator cell before comparing
against the allow-list, which meant `| --- | --- |` passed as
`---`. The documented rule requires the tight `|---|---|` form;
compare the raw cell so space-padded separators fail too.
Prettier pads markdown table cells for column alignment, which turns any
content change into a table-wide realignment diff. Markdown was only in
prettierignore for packages/kilo-vscode/; the root formatter still
repadded docs elsewhere (e.g. TESTING.md, kilo-docs, AGENTS.md).
Adds *.md to the root .prettierignore, documents the convention in
AGENTS.md, and adds script/check-md-table-padding.ts + a workflow to
enforce it. Existing padded tables in Kilo-owned docs have been
rewritten via the script's --fix mode.