Skip to content

feat(analyze): surface pinned files that are behind upstream - #21

Merged
flipvh merged 2 commits into
mainfrom
feat/cella-drift-convergence
Sep 21, 2026
Merged

flipvh merged 2 commits into
mainfrom
feat/cella-drift-convergence

Conversation

@flipvh

@flipvh flipvh commented Sep 21, 2026

Copy link
Copy Markdown
Member

Why

Pinned and ignored files win whole-file. When upstream also changed such a file since the last sync, its hunks are dropped without a trace: analyze showed the file like any other protected file and sync said nothing. A pinned tailwind.css in raak missed seven upstream @utility rules across three syncs this way.

This is the cella-cli half of the fork drift convergence work (pairs with cellajs/cella#1121).

What

Protected but behind upstream (7ef0a7d)

  • analyze-core: flags protected files both sides changed (upstreamChanged) and sizes the dropped change with one batched numstat (upstreamChangedLines)
  • display: new ⚠ protected but behind upstream section, superseding the plain pinned group; the sync summary lists protectedConflicts with the same hint, right when the drop happens
  • merge-engine: records protectedConflicts on the MergeResult (batch-restored protected files upstream changed, plus conflicts auto-resolved to the fork)
  • analyze --list/--json: includes these files in the all and protected scopes and emits the new fields
  • git: shared getDiffStat, lifted out of contributions

Upstream lines absent (e1af815)

  • The check above is relative to the last sync point, so a drop from an earlier sync reads as plain ahead afterwards. For every pinned (not ignored) ahead file whose blobs differ, one batched git diff --numstat --no-renames <upstream> HEAD records the deletion count as upstreamLinesAbsent, compared at the tips. Binaries are skipped.
  • The ↑ protected in fork section suffixes lines with · N upstream lines absent when N > 0; --json carries the field.

README documents the section and its last-sync-point limit.

Testing

  • New tests/protected-behind.test.ts (238 lines)
  • pnpm ts, pnpm lint, pnpm test green locally (18 files, 167 tests)

🤖 Generated with Claude Code

flipvh and others added 2 commits September 2, 2026 11:44
Pinned/ignored files win whole-file, so when upstream also changed one since
the last sync its hunks are dropped without a trace: analyze showed the file
like any other protected file and sync said nothing. A pinned tailwind.css
missed seven upstream @Utility rules across three syncs this way.

- analyze-core: flag protected files both sides changed (`upstreamChanged`)
  and size the dropped change with one batched numstat (`upstreamChangedLines`)
- display: new "protected but behind upstream" section (supersedes the plain
  pinned group), and the sync summary lists `protectedConflicts` with the same
  hint right when the drop happens
- merge-engine: record `protectedConflicts` (batch-restored protected files
  upstream changed + conflicts auto-resolved to fork) on the MergeResult
- analyze --list/--json: include these files in the all/protected scopes and
  emit the new fields; README documents the section and its last-sync-point limit
- git: shared `getDiffStat` (lifted from contributions)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The protected-but-behind check is relative to the last sync point, so a drop
that happened in an earlier sync reads as plain `ahead` afterwards. For every
pinned (not ignored) `ahead` file whose blobs differ, one batched
`git diff --numstat --no-renames <upstream> HEAD` records the deletion count
as `upstreamLinesAbsent`: lines upstream has that the fork lacks, compared at
the tips. Binaries are skipped.

The "protected in fork" section suffixes lines with `· N upstream lines absent`
when N > 0 and adds a hint to diff and decide; `--json` (and thus
`--scope protected`) carries the field.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@flipvh
flipvh merged commit 411a788 into main Sep 21, 2026
7 checks passed
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.

1 participant