| name | port-imageeditor |
| description | Use the local ShareX checkout as the source of truth for ShareX.ImageEditor, find the latest upstream commit that touches it, and port or sync the matching changes into the XerahS ShareX.ImageEditor submodule with path-aware diffing and build gates. |
| metadata | {"keywords":["imageeditor","porting","sync","sharex","submodule","avalonia","skia"],"last_updated":"2026-07-11T00:00:00.000Z"} |
Port ImageEditor: Local ShareX -> XerahS
Use this workflow whenever XerahS needs to catch up with the current ShareX.ImageEditor
state from the local ShareX repo.
Source of truth
On the known workstations, do not clone ShareX again. The local ShareX checkout is the
upstream reference.
Workspace root (resolve first)
The same sibling checkout layout exists on each machine. Resolve $ShareXTeamRoot from the
host OS before running any command in this skill:
| Host | $ShareXTeamRoot |
|---|
| Windows | C:\Users\liveu\source\repos\ShareX Team |
| macOS | /Users/mike/Projects/ShareX Team |
If the current XerahS working tree is not under that root, still use the mapped ShareX and
XerahS paths below for upstream reads and submodule work. Do not clone ShareX again just
because the active editor workspace lives elsewhere.
Cloud/CI fallback (no local ShareX checkout)
When the skill runs on a host without the ShareX Team layout (cloud agents, CI, fresh
VMs), the "do not clone" rule does not apply. Instead:
- Clone upstream once, blobless for speed:
git clone --filter=blob:none https://github.com/ShareX/ShareX.git /tmp/ShareX
- Use
/tmp/ShareX wherever this skill says $ShareXTeamRoot/ShareX.
- Use the current XerahS working tree as
$ShareXTeamRoot/XerahS, and run
git submodule update --init ShareX.ImageEditor first if the submodule directory is
empty.
- Create a base worktree for divergence triage (see step 2e-triage):
git -C /tmp/ShareX worktree add /tmp/sharex-base <last_synced_sharex_hash>
Linux hosts build the ImageEditor project, the desktop solution, and the test suite fine
(EnableWindowsTargeting is already configured), so all verification gates below apply
unchanged.
Path map
All paths below are derived from $ShareXTeamRoot. In command examples, substitute the
resolved root for $ShareXTeamRoot.
| Role | Path |
|---|
| Upstream ShareX repo | $ShareXTeamRoot/ShareX |
| Upstream source tree | $ShareXTeamRoot/ShareX/ShareX.ImageEditor |
| XerahS root | $ShareXTeamRoot/XerahS |
| XerahS ImageEditor repo | $ShareXTeamRoot/XerahS/ShareX.ImageEditor |
| XerahS ImageEditor code root | $ShareXTeamRoot/XerahS/ShareX.ImageEditor/src/ShareX.ImageEditor |
All command examples use forward slashes. They work on Windows, macOS, and Linux for
git -C, cd, and dotnet build.
Hardcoded local roots are intentional here. They make this workflow faster and more reliable
across the known Windows and macOS workstations.
Set the root once per session before running the commands below:
# Windows PowerShell
$ShareXTeamRoot = 'C:\Users\liveu\source\repos\ShareX Team'
ShareXTeamRoot="/Users/mike/Projects/ShareX Team"
In PowerShell examples, "$ShareXTeamRoot/..." works on Windows because git -C accepts
forward slashes. In zsh/bash, use "$ShareXTeamRoot/..." the same way.
Core rules
- The newest relevant upstream commit must be resolved from the local ShareX repo's git history, not guessed.
- Diff against the mapped XerahS code root. The upstream source lives at
ShareX/ShareX.ImageEditor/...; the target code lives at XerahS/ShareX.ImageEditor/src/ShareX.ImageEditor/....
- Scan every relevant upstream commit from the previous sync point through the newest relevant commit, not just the tip commit.
- Build a holistic understanding of the bugs fixed and features added across that whole commit window before changing XerahS.
- Before implementing anything, publish a concise implementation manifest that lists every bug fix and enhancement identified from the new ShareX commits.
- For every manifest item, check whether XerahS already fixed it, implemented it differently, partially implemented it, or has a better local behavior that must be preserved.
- Do not start implementing an individual bug fix or enhancement until it appears in the manifest with its source commit, affected files, XerahS status, and intended XerahS mapping.
- Prefer the best combined design over a direct ShareX copy: preserve superior XerahS behavior, import superior ShareX behavior, and write a custom implementation when that is the cleanest integration.
- Read the affected upstream and XerahS files to clarify intent, control flow, rendering behavior, and wiring before re-implementing anything ambiguous.
- Preserve XerahS-only repository-level differences such as the submodule's
src/ layout, multi-targeting, and any confirmed host integration changes.
- Do not overwrite XerahS-specific fixes blindly. If a target file already diverged for Avalonia or host integration, port the upstream intent instead of doing a raw replace.
- This is not a blind cherry-pick workflow. Review the upstream change set, understand the behavior being introduced or fixed, and then map that behavior into the Avalonia submodule.
- Re-implement the upstream behavior in the XerahS ImageEditor submodule after understanding it, instead of mechanically transplanting diffs.
- Build before claiming completion.
- Commit each completed bug fix and enhancement separately in the
ShareX.ImageEditor submodule. Do not bundle unrelated manifest items into one port commit.
- If verification passes and the user did not ask to pause, push the submodule commits and then commit and push the XerahS root pointer update.
Step 0 - Resolve the upstream commit range
0a0 - Align the XerahS root and submodule safely
Before resolving the ShareX range, make sure the XerahS root branch and the
ShareX.ImageEditor submodule are in a predictable state.
git -C "$ShareXTeamRoot/XerahS" status --short --branch
git -C "$ShareXTeamRoot/XerahS" submodule status
git -C "$ShareXTeamRoot/XerahS/ShareX.ImageEditor" status --short --branch
If the root branch is behind and there are no conflicting local changes, prefer a
fast-forward pull that does not recurse into submodules:
$env:GIT_TERMINAL_PROMPT = '0'
git -C "$ShareXTeamRoot/XerahS" pull --ff-only --no-recurse-submodules
This avoids a root pull hanging on nested submodule fetches. If a previous pull or
fetch stalls with no lock held, stop only the stale git processes and retry the
root fast-forward with --no-recurse-submodules.
After the root is current, align the submodule branch with its remote before
porting. If a local submodule commit is a cherry-pick duplicate, let git pull --rebase skip it rather than preserving a duplicate patch:
$env:GIT_TERMINAL_PROMPT = '0'
git -C "$ShareXTeamRoot/XerahS/ShareX.ImageEditor" pull --rebase
Do not stage the root submodule pointer update that results from this housekeeping
until after the port build gates pass.
0a - Confirm the local ShareX checkout is current
git -C "$ShareXTeamRoot/ShareX" status --short
git -C "$ShareXTeamRoot/ShareX" branch --show-current
git -C "$ShareXTeamRoot/ShareX" rev-parse HEAD
git -C "$ShareXTeamRoot/ShareX" fetch --prune
git -C "$ShareXTeamRoot/ShareX" status --short --branch
Use the checked-out branch as the default upstream branch unless the user requests a different ref.
If the local ShareX checkout is behind its upstream tracking branch, pull it before resolving the ImageEditor range:
git -C "$ShareXTeamRoot/ShareX" pull --ff-only
If ShareX has local uncommitted changes, do not overwrite them. Prefer:
- If the changes are unrelated and the checkout is only needed for read-only upstream assessment, use
git pull --rebase --autostash so the newest source is available locally.
- If the changes conflict with the pull or look relevant to
ShareX.ImageEditor, stop and report that the local ShareX checkout must be cleaned or reviewed before porting.
After pulling, record the updated ShareX HEAD and use that local source for the rest of the assessment. This keeps the upstream code local and fast to inspect without cloning ShareX again.
0b - Find the latest ShareX commit that touches ShareX.ImageEditor
git -C "$ShareXTeamRoot/ShareX" `
log -1 --format="%H %cs %s" -- ShareX.ImageEditor
This is the latest relevant upstream commit. Record it.
0c - Find the last recorded sync point in XerahS
Read $ShareXTeamRoot/XerahS/ShareX.ImageEditor/PORT_STATUS.md.
Expected fields:
ShareX.ImageEditor commit: <hash>
XerahS submodule last synced to: <hash>
If the file is missing or stale, derive the baseline from repo history and note the assumption in the final update.
0d - List pending upstream commits
git -C "$ShareXTeamRoot/ShareX" `
log --reverse --oneline <last_synced_sharex_hash>..HEAD -- ShareX.ImageEditor
Use this list to decide whether the catch-up is:
- Low risk: isolated bug fix in a small file
- Medium risk: touches controllers, view models, or multiple files
- High risk: adds files, changes tooling or rendering, or updates editor interaction behavior
Do not treat this commit list as a queue for blind cherry-picks. Use it as a review list for semantic porting.
Read the whole queue from oldest to newest so you understand how fixes and features build on each other.
Step 1 - Map source paths to target paths
The ShareX tree and XerahS submodule do not have the same repository layout.
| Upstream path | Target path |
|---|
ShareX.ImageEditor/Assets/... | ShareX.ImageEditor/src/ShareX.ImageEditor/Assets/... |
ShareX.ImageEditor/Core/... | ShareX.ImageEditor/src/ShareX.ImageEditor/Core/... |
ShareX.ImageEditor/Hosting/... | ShareX.ImageEditor/src/ShareX.ImageEditor/Hosting/... |
ShareX.ImageEditor/Presentation/... | ShareX.ImageEditor/src/ShareX.ImageEditor/Presentation/... |
ShareX.ImageEditor/ShareX.ImageEditor.csproj | ShareX.ImageEditor/src/ShareX.ImageEditor/ShareX.ImageEditor.csproj |
Do not diff the upstream folder against the submodule repo root. Always diff it against
src/ShareX.ImageEditor.
Step 2 - Inspect the exact upstream delta
2a - List files changed since the last sync
git -C "$ShareXTeamRoot/ShareX" `
diff --name-only <last_synced_sharex_hash>..HEAD -- ShareX.ImageEditor
2b - Review each pending commit with stats
git -C "$ShareXTeamRoot/ShareX" `
show --stat --summary --oneline <sharex_commit>
Also inspect the actual patch for behavior-critical commits:
git -C "$ShareXTeamRoot/ShareX" `
show <sharex_commit> -- ShareX.ImageEditor
For a real catch-up, do this for every commit in the pending range from the last synced hash to the newest relevant hash.
Summarize for yourself:
- which user-visible features were added
- which bugs were fixed
- which commits depend on earlier commits in the range
- which files are the authoritative implementation points
2c - Publish the implementation manifest before editing
Before changing files, post a concise manifest in chat. This is a mandatory gate for the port session.
The manifest must include every bug fix and enhancement identified in the pending ShareX commits, grouped by implementation item rather than by raw file. Each item must include:
- Type:
Bug fix, Enhancement, Refactor with behavior impact, or Infrastructure
- Source commit(s): the ShareX hash and short subject
- Upstream behavior: what changed for users or editor internals
- XerahS status:
missing, already fixed, implemented differently, partially implemented, or conflicts with XerahS
- Target files: the mapped XerahS files expected to change
- Decision: raw sync, manual merge, custom implementation, keep XerahS behavior, or intentional skip with reason
- Rationale: why that decision gives XerahS the best behavior
- Commit plan: the intended standalone submodule commit subject for this item, or
none when the item is kept/skipped
Use this shape:
## ImageEditor Port Manifest
- [ ] Bug fix: <short name>
Source: `<hash>` <subject>
Upstream behavior: <one sentence>
XerahS status: <missing/already fixed/implemented differently/partially implemented/conflicts>
Target files: `<mapped/file.cs>`, `<mapped/file.axaml>`
Decision: <raw sync/manual merge/custom implementation/keep XerahS/skip>
Rationale: <why this is the best XerahS outcome>
Commit plan: `[ShareX.ImageEditor] [Fix] <short description> from ShareX@<hash>`
- [ ] Enhancement: <short name>
Source: `<hash>` <subject>
Upstream behavior: <one sentence>
XerahS status: <missing/already fixed/implemented differently/partially implemented/conflicts>
Target files: `<mapped/file.cs>`
Decision: <raw sync/manual / / />
Rationale:
Commit plan:
During implementation, work against this manifest. Announce the item being implemented before editing it, and update the item status as it is completed or intentionally skipped.
Do not use raw sync as the default. It is only acceptable after comparing the mapped XerahS file and confirming there is no local fix, no different design, and no host-specific behavior worth preserving.
When multiple manifest items share prerequisite scaffolding, such as a new enum, helper, or control required by later items, either:
- include the shared scaffold in the first item that needs it when that keeps the commit coherent, or
- create a separate preparatory commit with
[ShareX.ImageEditor] [Infrastructure] ... before the dependent bug-fix/enhancement commits.
Do not create one large "sync latest ShareX changes" submodule commit unless the pending range has exactly one cohesive manifest item.
For very large ranges (100+ commits) where central files such as MainViewModel.cs,
EditorCore.cs, EditorView.axaml, and AnnotationToolbar.axaml are touched by many
manifest items at once, grouping is acceptable: commit each cleanly file-scoped feature
(new tool windows, new partial-class features, asset regens) separately, and land the
interleaved central files in one final [Port] commit that lists the covered items in its
body. Note in PORT_STATUS.md that intermediate commits only build as a batch. Prefer the
manifest to still list every item individually even when commits are grouped.
2d - Read code to remove ambiguity
If the commit message or patch alone is not enough, read the upstream implementation files and the current XerahS counterparts before editing.
Typical files to inspect:
- controllers
- view models
- rendering and visual factory code
- annotation model classes
- views and control markup
- the target
.csproj for new files or assets
2e - Compare mapped files, not raw repo roots
For each changed upstream file ShareX.ImageEditor/<relative_path> compare it to:
$ShareXTeamRoot/XerahS/ShareX.ImageEditor/src/ShareX.ImageEditor/<relative_path>.
If the target file does not exist, it is a net-new addition and therefore high risk.
2e-triage - Automate divergence triage for large ranges
For ranges with dozens of changed files, do not eyeball each file. Check out the last
synced upstream commit into a worktree (git worktree add /tmp/sharex-base <last_sync>)
and script a three-way classification of every upstream-changed file:
NEW: absent from the XerahS code root — sync it in as a new file.
SAFE_SYNC: the XerahS file equals the upstream base version after normalizing the
license-header region, BOM, CRLF-vs-LF, and trailing whitespace — a raw sync from
upstream HEAD is safe because XerahS never diverged in content.
DIVERGED: real content differences — these carry XerahS adaptations and require a
manual merge.
For each DIVERGED file, produce two normalized diffs: base -> xerahs (the XerahS
adaptation to preserve) and base -> head (the upstream change to port). Files whose
base -> xerahs delta is only blank lines or an encoding artifact can be treated as
SAFE_SYNC. This triage turned a 149-file range into 19 real merges in the 2026-07-11
port.
2e-headers - Header, BOM, and EOL policy during syncs
Upstream ShareX files carry a UTF-8 BOM, CRLF line endings, and the ShareX license
header. The XerahS submodule stores UTF-8 without BOM, LF endings, and a mix of the
ShareX.ImageEditor - The UI-agnostic Editor library for ShareX header and headerless
files. When syncing:
- Strip the BOM and convert CRLF to LF.
- For existing files, preserve the target file's current header state byte-for-byte
(including "no header") and replace only the body below it.
- For new
.cs files, add the submodule-standard ShareX.ImageEditor header wording.
- Never let a raw copy replace the XerahS header with the upstream ShareX wording.
2f - Compare behavior, not just text
For every manifest item, answer these questions before editing:
- Is the same bug already fixed in XerahS under a different implementation?
- Is the ShareX fix better, worse, or complementary to the XerahS behavior?
- Does XerahS have host integration, Avalonia-specific behavior, tests, or persistence hooks that ShareX does not have?
- Can the best result be achieved by combining both implementations instead of copying either one wholesale?
- Is a small custom implementation clearer than copying the upstream patch?
If XerahS already has an equal or better implementation, keep it and record the item as keep XerahS behavior or skip.
If both implementations solve different parts of the problem, create a manual merge or custom implementation and record the rationale in PORT_STATUS.md.
Step 3 - Port or sync safely
3a - When a raw file sync is acceptable
Raw file sync is an exception, not the normal path. You may replace the target file with the upstream version only when all of these are true:
- The file lives under
Core/, Presentation/, Hosting/, or Assets/ and maps cleanly into src/ShareX.ImageEditor
- The target file was compared and does not contain a relevant XerahS fix, alternate implementation, host integration, persistence hook, test-supported behavior, or Avalonia-specific adaptation that would be lost
- The upstream change is exactly what XerahS needs and there is no repo-layout-only difference inside the file
- The manifest item explicitly marks the decision as
raw sync with a short rationale
3b - When manual porting is required
Port the intent instead of copying the whole file when any of these are true:
- The target file contains XerahS-specific Avalonia, SkiaSharp, or host wiring that is not present upstream
- The target file already diverged beyond the pending upstream commit range
- The upstream file assumes repository or project settings that do not match the submodule
- The upstream commit adds a feature partially present in XerahS and a direct replace would regress local behavior
- XerahS already has a different fix for the same bug and the best result needs parts of both implementations
- The upstream code is correct for ShareX but a custom XerahS implementation would be simpler, safer, or better aligned with current XerahS architecture
Manual porting usually means:
- keep the XerahS file as the base
- apply the upstream behavior in small, reviewable hunks
- re-implement the bug fix or feature after understanding the whole upstream flow
- keep any superior XerahS behavior and merge only the missing upstream behavior
- add or update tests for bugs where the upstream fix differs from the XerahS implementation
- rebuild after behavior-critical controller, view model, rendering, or view changes
- only replace the whole file when the diff is layout-only and no XerahS adaptation would be lost
When a transformed upstream patch cannot apply because of expected XerahS
divergence, a mapped final-state sync is acceptable as an implementation aid, but
only after the manifest has been posted. After such a sync, immediately re-apply
and verify these known XerahS adaptations before building:
Annotation.cs: keep JsonPolymorphic(TypeDiscriminatorPropertyName = "$type"),
JsonIgnore on computed/runtime state, and XerahS StepTailStyle; add any new
upstream JsonDerivedType entries such as cursor annotations.
BaseEffectAnnotation.cs / ImageAnnotation.cs: keep [JsonIgnore] on the runtime
bitmap properties (EffectBitmap, ImageBitmap) and the
System.Text.Json.Serialization using.
EditorCore.cs: keep GetAnnotationsSnapshotForPersistence(),
RestoreAnnotations(...), and number-counter resync after restore/renumbering.
MainViewModel.cs: keep ApplicationName and EditorTitle because XerahS host
windows bind to that title contract.
MainViewModel.ImageState.cs: keep CreateSourceImageCopyForPersistence() and
GetAnnotationSnapshotForPersistence().
EditorView.CoreBridge.cs: keep GetAnnotationSnapshot() and
RestoreAnnotations(...) (with number-counter and history-state resync).
AvaloniaIntegration.cs: preserve XerahS task-mode behavior, especially
ShowFileMenu = !taskMode and start-screen suppression, while adding new
upstream event wiring.
EditorIcons.cs: preserve XerahS-only icon constants such as tail-style icons
(TailStyleTriangle, TailStyleArrow) when upstream icon syncs replace the file.
NumberAnnotation.cs / StepControl.cs: XerahS has the tail-style system
(StepTailStyle Triangle/Arrow, TryGetArrowTailOutline,
TryGetCircleSegmentExitPoint, arrow tail rendering). Merge upstream step
features (StepType, IsBold, TailEnabled, tail geometry changes) into that system
instead of replacing it; upstream deletes TryGetCircleSegmentExitPoint, but the
XerahS arrow tail still needs it.
- Theming file names: upstream renamed
ImageEditorStyles.axaml /
ImageEditorTheme.axaml to AppStyles.axaml / AppTheme.axaml. Keep the XerahS
names and rewrite / URI references in synced
files back to the XerahS names: root (MainWindow resources),
, and the XerahS
StyleInclude all bind to the XerahS URIs.
PowerShell versions in this repo may not support Set-Content -Encoding utf8NoBOM. For mechanical header normalization during mapped syncs, use
[System.Text.UTF8Encoding]::new($false) with [System.IO.File]::WriteAllText(...)
instead of relying on that encoding name.
3c - When to write a custom implementation
Write a custom implementation when the upstream patch exposes the desired behavior but the XerahS architecture calls for a different shape.
Common cases:
- XerahS already has a related service, adapter, or persistence hook that should own the behavior.
- ShareX solves the bug in UI code, but XerahS should solve it in
EditorCore or a shared controller.
- The upstream change duplicates logic already centralized in XerahS.
- The upstream behavior is useful, but its exact code would regress RegionCapture, embedded editor mode, tests, serialization, or host integration.
- Combining both implementations would otherwise create duplicated state or unclear ownership.
Record custom implementations in PORT_STATUS.md with the source ShareX commit, the XerahS files changed, and the reason for not copying upstream code.
3d - Preserve known XerahS repository-level differences
Keep these unless the user explicitly asks to change them:
src/ShareX.ImageEditor repository layout
- XerahS-specific solution or project structure
- XerahS multi-targeting or packaging differences
- Any host integration already verified in XerahS
3e - New-file checklist
For each new upstream file:
- Create the mapped target directory if needed.
- Add the file under
src/ShareX.ImageEditor.
- Update the target
.csproj only if the new file requires an explicit item entry.
- Search for references to the new type or view and port the wiring in the same session.
Step 4 - Verification gates
4a - Targeted ImageEditor build
cd "$ShareXTeamRoot/XerahS"
dotnet build "ShareX.ImageEditor/src/ShareX.ImageEditor/ShareX.ImageEditor.csproj" -m:1
If it stalls, stop it before 5 minutes and clear the lock before retrying.
4b - Full solution build
cd "$ShareXTeamRoot/XerahS"
dotnet build "src/desktop/XerahS.sln" -m:1
This must finish with 0 errors before any push.
4c - Standalone submodule solution and tests
The submodule ships its own solution with a standalone app project that consumes
AvaloniaIntegration; API changes that pass the XerahS build can still break it:
cd "$ShareXTeamRoot/XerahS/ShareX.ImageEditor"
dotnet build "ShareX.ImageEditor.sln" -m:1
Also run the XerahS test suite; RegionCapture adapter and editor behavior tests live
there:
cd "$ShareXTeamRoot/XerahS"
dotnet test "tests/XerahS.Tests/XerahS.Tests.csproj" -m:1
Step 5 - Update tracking
After the catch-up:
- Update
$ShareXTeamRoot/XerahS/ShareX.ImageEditor/PORT_STATUS.md
- Record:
- latest upstream ShareX commit used
- previous recorded sync point
- files added or updated
- risk summary
- adaptations kept for XerahS
Suggested status block:
## Port Activity (2026-04-09)
- Previous recorded ShareX sync: `<old_hash>`
- Latest upstream ShareX commit touching ShareX.ImageEditor: `<new_hash>`
- Result: `Caught up through <new_hash>`
- Notes: `<manual adaptations or intentional skips>`
Step 6 - Commit discipline
The submodule is a shared library repo, so submodule commits do not use the XerahS version prefix.
Commit each completed manifest item separately in the ShareX.ImageEditor submodule.
Use these submodule commit formats:
[ShareX.ImageEditor] [Fix] <bug fix description> from ShareX@<hash>
[ShareX.ImageEditor] [Enhancement] <feature description> from ShareX@<hash>
[ShareX.ImageEditor] [Infrastructure] <shared prerequisite description>
[ShareX.ImageEditor] [Port] <description> from ShareX@<hash>
Use [Port] only for cohesive changes that are not cleanly a fix or enhancement, such as a behavior-impacting refactor. If one upstream commit contains several unrelated user-visible fixes or enhancements, split the XerahS commits by manifest item, not by upstream commit.
Before each submodule commit:
- Stage only the files/hunks for that manifest item.
- Run the smallest relevant build or test if the item is behavior-critical and fast enough.
- Commit with the planned subject.
- Continue to the next manifest item.
If a later item needs to amend a previous item because of a discovered integration issue, prefer a new targeted follow-up commit unless history has not been pushed and the scope is still clearly the same manifest item.
Then update the XerahS root repo to point to the new submodule commit.
Step 7 - Push discipline
After verification succeeds:
- Confirm every implemented manifest item has its own
ShareX.ImageEditor submodule commit, except items explicitly kept or skipped.
- Push the submodule branch after the full verification gates pass.
- Stage the updated submodule pointer and any root tracking or skill changes in
XerahS.
- Commit the XerahS root repo using the next unreleased XerahS version prefix. The root commit may summarize the batch because it only records the final submodule pointer and host/test integration.
- Push the XerahS root branch.
Do not stop after a local commit unless the user explicitly asks to pause before push.
Fast path for this repo
For the common "catch up XerahS to the latest local ShareX state" task:
- Resolve
$ShareXTeamRoot for the current host, or use the cloud/CI fallback clone when the ShareX Team layout does not exist.
- Read
PORT_STATUS.md to get the last synced ShareX hash.
- Run
git -C "$ShareXTeamRoot/ShareX" fetch --prune and check git -C "$ShareXTeamRoot/ShareX" status --short --branch.
- If the local ShareX checkout is behind, run
git -C "$ShareXTeamRoot/ShareX" pull --ff-only; use --rebase --autostash only for unrelated local ShareX changes that must be preserved.
- Run
git -C "$ShareXTeamRoot/ShareX" log -1 --format="%H %cs %s" -- ShareX.ImageEditor.
- Run
git -C "$ShareXTeamRoot/ShareX" diff --name-only <last_sync>..HEAD -- ShareX.ImageEditor.
- Map each changed upstream file into
XerahS/ShareX.ImageEditor/src/ShareX.ImageEditor.
- For large ranges, run the 2e-triage classification (NEW / SAFE_SYNC / DIVERGED) against a base worktree before deciding sync strategy per file.
- Review every upstream commit in the range so you understand the complete feature and bug-fix set.
- For each item, compare the upstream behavior against the current XerahS behavior and decide whether it is missing, already fixed, implemented differently, partially implemented, or conflicting.
- Post the ImageEditor Port Manifest listing every identified bug fix and enhancement, including XerahS status, decision, and rationale, before editing.
- Read upstream and XerahS code where needed to confirm how the behavior works.
- Port, manually merge, keep XerahS behavior, or write a custom implementation as appropriate; do not blind cherry-pick or raw-copy diverged Avalonia files.
- Commit each completed bug fix/enhancement as a separate
ShareX.ImageEditor submodule commit, keeping shared infrastructure separate when needed.
- Build the ImageEditor project, then the XerahS solution.
- Update
PORT_STATUS.md, then push the submodule commits and commit/push the root pointer separately.