|
| 1 | +--- |
| 2 | +name: add-rebase-rules |
| 3 | +description: Generates .rebase add/override/replace rules from a commit that changes code/ files, updates rebase.sh conflict routing, and appends .rebase/CHANGELOG.md. Use when asked to add rebasing rules for a commit or PR. |
| 4 | +argument-hint: [commit-sha] |
| 5 | +disable-model-invocation: true |
| 6 | +--- |
| 7 | + |
| 8 | +# Add Rebase Rules |
| 9 | + |
| 10 | +Create or update rebasing rules for Che-specific changes that touch VS Code subtree files under `code/`. |
| 11 | + |
| 12 | +Use this skill when the user gives a commit SHA (or PR/commit URL) and asks to add rebasing rules. |
| 13 | + |
| 14 | +## Required input |
| 15 | + |
| 16 | +- A commit SHA is expected in `$ARGUMENTS`. |
| 17 | +- If `$ARGUMENTS` is empty, ask the user for a commit SHA before proceeding. |
| 18 | + |
| 19 | +## Scope and exclusions |
| 20 | + |
| 21 | +Only consider changed files under `code/`. |
| 22 | + |
| 23 | +Never create rebasing rules for: |
| 24 | +- `code/extensions/che-*/**` |
| 25 | +- any `**/package-lock.json` |
| 26 | + |
| 27 | +Important: |
| 28 | +- A file can be under `code/` and still be Che-only (for example `code/src/.../che/...` newly created by Che). Do not create a rule for such files if they are not upstream VS Code files. |
| 29 | +- Still create rules for the upstream file(s) that import/use those Che-only helpers. |
| 30 | + |
| 31 | +## Workflow |
| 32 | + |
| 33 | +1. Resolve the target commit and collect changed files |
| 34 | + - If input is a URL, extract the SHA. |
| 35 | + - Get changed files: |
| 36 | + - `git show --name-only --pretty='' <sha> | sort -u` |
| 37 | + - Filter to the rule candidate set: |
| 38 | + - include: files starting with `code/` |
| 39 | + - exclude: `code/extensions/che-*/**` |
| 40 | + - exclude: `**/package-lock.json` |
| 41 | + |
| 42 | +2. Classify each candidate file |
| 43 | + - `*/package.json` -> JSON merge rule (`.rebase/add/` and/or `.rebase/override/`) |
| 44 | + - Other modified upstream files -> replace rule (`.rebase/replace/<path>.json`) |
| 45 | + - Newly added Che-only files with no upstream counterpart -> skip (no rule needed) |
| 46 | + |
| 47 | +3. Create or update JSON merge rules for `package.json` |
| 48 | + - Preserve only minimal changed subtree (do not copy entire package.json). |
| 49 | + - Use: |
| 50 | + - `.rebase/add/<path>` for new keys or additive nested values |
| 51 | + - `.rebase/override/<path>` when overriding existing values must be explicit |
| 52 | + - It is valid to use both for one file. |
| 53 | + - Keep file formatting consistent with existing `.rebase` JSON style (2-space indentation). |
| 54 | + |
| 55 | +4. Create or update replace rules for non-JSON files |
| 56 | + - File path: `.rebase/replace/<original-path>.json` |
| 57 | + - Format: JSON array of objects with `from` and `by`. |
| 58 | + - Add one rule per changed hunk, using stable and unique snippets. |
| 59 | + - Prefer the smallest safe snippet that is unlikely to change accidentally. |
| 60 | + - If replacement is multiline, encode using escaped newlines/tabs in JSON consistently with existing files. |
| 61 | + - For multiline `from` snippets, start at the first non-whitespace token (avoid anchoring on leading indentation only). |
| 62 | + - Prefer replacing the whole logical block (`if (...) { ... }`) rather than only an inner line fragment, so closing braces remain structurally correct. |
| 63 | + |
| 64 | +5. Update `rebase.sh` conflict routing |
| 65 | + - Ensure each file that now has a new rebasing rule is routable in `resolve_conflicts`. |
| 66 | + - For `package.json` files: |
| 67 | + - add `elif` branch calling `apply_package_changes_by_path "$conflictingFile"` (or equivalent existing pattern). |
| 68 | + - For non-JSON replace rules: |
| 69 | + - use `apply_changes "$conflictingFile"` for line-based replacements. |
| 70 | + - For multiline replacements, `rebase.sh` has **two** handlers — do not always default to one: |
| 71 | + - `apply_changes_multi_line "$conflictingFile"` — higher-level wrapper that resets the file (`git checkout --theirs`), calls `apply_multi_line_replace`, then stages the result (`git add`). |
| 72 | + - `apply_multi_line_replace "$conflictingFile"` — low-level function that performs the Perl multiline replacement directly, without git checkout/add. |
| 73 | + - Before adding a routing branch, inspect the existing `resolve_conflicts` block in `rebase.sh` and look at how other files in the same area are routed. Match the handler already used for similar files. For example, if neighboring entries call `apply_multi_line_replace` directly, use that; if they use `apply_changes_multi_line`, use that instead. |
| 74 | + - Do not add duplicate branches. |
| 75 | + |
| 76 | +6. Update `.rebase/CHANGELOG.md` |
| 77 | + - Append a new entry in existing format: |
| 78 | + - `#### @<author>` |
| 79 | + - commit/PR link (or commit SHA if no link is available) |
| 80 | + - list only files for which rebasing rules were added/updated |
| 81 | + - separator `---` |
| 82 | + |
| 83 | +7. Validate before finishing |
| 84 | + - Determine the upstream ref from `rebase.sh` and use that exact ref for validation (do not hardcode a release branch in the skill output). |
| 85 | + - Example source of truth in `rebase.sh`: `UPSTREAM_VERSION=$(git rev-parse upstream-code/release/1.108)` |
| 86 | + - If the script later points to `upstream-code/main` or another release branch, use that new ref instead. |
| 87 | + - `bash -n rebase.sh` |
| 88 | + - JSON validation for changed `.rebase/**/*.json` files (`jq empty <file>`) |
| 89 | + - For each changed `.rebase/replace/**/*.json`, verify every `from` exists in the upstream file content before finishing. |
| 90 | + - Example: `git show <upstream-ref>:<path-without-code-prefix>` and compare with the `from` snippet. |
| 91 | + - `path-without-code-prefix` means the same file path but without the leading `code/` (because `upstream-code` stores VS Code sources at repo root). |
| 92 | + - Dry-run the generated rule using the same replacement path as `rebase.sh` (Perl-based multiline replace), not a language-native `.replace(...)`. |
| 93 | + - Include at least one test case where `from`/`by` contains `$` (for example template literals like `${key}`) and confirm replacement still succeeds. |
| 94 | + - Re-check exclusions: |
| 95 | + - no rules for `code/extensions/che-*` |
| 96 | + - no rules for `package-lock.json` |
| 97 | + - Ensure every changed rule file is actually referenced by logic in `rebase.sh` when required. |
| 98 | + |
| 99 | +## Decision notes |
| 100 | + |
| 101 | +- Goal is to protect Che-specific behavior during upstream subtree rebases while keeping deltas in upstream files minimal. |
| 102 | +- Prefer moving larger Che logic into Che-owned files and keeping upstream file edits small; then create replace rules only for the upstream file edits. |
| 103 | +- When unsure between `add` vs `override` for JSON, follow existing `.rebase` conventions in neighboring files and keep the smallest rule payload that reproduces the required result. |
| 104 | + |
| 105 | +## Examples |
| 106 | + |
| 107 | +- Dependency override updates across many `code/**/package.json` files: |
| 108 | + - Example commit: `04b7984047fec31dd6993bd299f6698750c63d08` |
| 109 | + - Matching rule-update style: `eec9cd1e9e199ce9a0eb2f6e3bd1dad6fc258413` |
| 110 | + |
| 111 | +- Source-level VS Code file changes protected by replace rules: |
| 112 | + - Example PR changes: `https://github.com/che-incubator/che-code/pull/617/changes` |
| 113 | + - Matching rule commit: `https://github.com/che-incubator/che-code/pull/617/changes/e794c63f01d116b0b92d5ecd220247e13a5ba946` |
0 commit comments