Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .cursor/rules/branch-backport.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
description: Generic workflow for backporting changes from a source branch to a target branch without regressions
alwaysApply: true
---

# Branch backport rules (generic — mandatory)

Use whenever porting work **from a source branch to a target branch** (release line, long-lived dev branch, stacked PR parent, etc.).

Set branch names once per task (examples: `SOURCE=feature/x` `TARGET=main`, or `SOURCE=unomi-3-dev` `TARGET=master`):

```bash
cd "$(git rev-parse --show-toplevel)"
git fetch origin
SOURCE=<source-branch> # where the change lives today
TARGET=<target-branch> # where it must land (canonical for existing files)
```

Repo-specific overlays (e.g. UNOMI-875): `.cursor/rules/unomi-3-dev-backport.mdc` — read **after** this file when applicable.

## Never do this

- **Never** `git checkout origin/$SOURCE -- <path>` on files that **already exist on** `origin/$TARGET`.
- **Never** assume “file differs on source ⇒ target is missing it” — the target often has **review-only fixes** the source never received.
- **Never** `git cherry-pick` commits from `$SOURCE` history onto `$TARGET` for bulk backport work without per-commit review (source history is often pre-merge noise).
- **Never** downgrade pinned versions on `$TARGET` (images, BOM, lockfiles) to match `$SOURCE` without explicit review.

## Always do this

1. **Branch from** `origin/$TARGET` (or current stack parent), not from `$SOURCE`.
2. **Inventory:** `git diff --stat origin/$TARGET origin/$SOURCE -- <paths>` — size only; not a port list.
3. **Commit history audit** on every path that exists on `$TARGET` — see below.
4. **Classify each path:** ADD (new on target) · MODIFY (exists on target) · MERGE (build/CI/deps — both sides changed).
5. **Port:**
- **ADD:** `git checkout origin/$SOURCE -- <new-file>` is OK if the file is absent on `$TARGET`.
- **MODIFY:** start from `origin/$TARGET`; apply additive hunks from `$SOURCE` by hand.
- **MERGE:** never replace whole file; keep `$TARGET`-only lines while adding `$SOURCE` features.
6. **Pre-commit diff audit** on every modified existing file — see below.
7. **Build/test** affected modules before opening PR; state in PR body that history + diff audits were run.

## Commit history audit (MODIFY / MERGE)

> Read **`$TARGET` history** to protect review work. Do **not** use `$SOURCE` commit SHAs as a port shortcut.

```bash
PATH=path/to/file

# Target-only commits (review PRs, bugfixes never merged to source):
git log origin/$SOURCE..origin/$TARGET --oneline -- "$PATH"

# Recent target context (PR numbers in subjects):
git log origin/$TARGET -20 --oneline -- "$PATH"

# If your branch deletes lines, trace them on target:
git diff origin/$TARGET -- "$PATH"
git blame origin/$TARGET -L <start>,<end> -- "$PATH"
git log -1 --format='%h %s (%ci)' <commit-from-blame>
```

| Signal | Interpret |
|---|---|
| Non-empty `origin/$SOURCE..origin/$TARGET` log | Target has fixes source lacks — **do not overwrite** file from source |
| Empty target-only log | Still run diff audit; may be safe ADD or symmetric drift |
| Non-empty target-only log **and** substantive removals in your branch | **STOP** — read those commits before continuing |

Optional: `git log origin/$TARGET..origin/$SOURCE --oneline -- "$PATH"` lists what source added — candidate material, **not** a license to blind checkout.

## Pre-commit diff regression audit

```bash
PATH=path/to/file

# What target has that source lacks (fixes we must keep):
git diff origin/$SOURCE origin/$TARGET -- "$PATH"

# What our branch removes from target (should be empty or whitespace/comments only):
git diff origin/$TARGET -- "$PATH" | rg '^-' | rg -v '^---|^-import |^-package |^-\s*$|^- \*|^-\s*/\*|^-\s*\*'

# Gate: substantive removal count (threshold ~5 → investigate)
git diff origin/$TARGET -- "$PATH" | rg '^-' | rg -v '^---|^-import |^-package |^-\s*$|^- \*|^-\s*/\*|^-\s*\*' | wc -l
```

Cross-check: if target-only log is non-empty **and** removal count > 0, read target-only commits before committing.

## Validation before PR

- [ ] `SOURCE` / `TARGET` named in PR description
- [ ] Commit history audit for every modified **existing** file
- [ ] No substantive `-` lines vs `origin/$TARGET` on modified existing files
- [ ] Module compile / targeted tests for touched areas
55 changes: 55 additions & 0 deletions .cursor/rules/unomi-3-dev-backport.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
description: UNOMI-875 overlay — backporting unomi-3-dev → master (extends branch-backport.mdc)
alwaysApply: true
---

# unomi-3-dev → master (UNOMI-875 Phase 2)

**Generic workflow first:** `.cursor/rules/branch-backport.mdc` (history audit, diff audit, ADD/MODIFY/MERGE).

For this epic, set:

```bash
SOURCE=unomi-3-dev
TARGET=master
```

Local tracker (git-ignored): `.local-notes/unomi-3-dev-backport-plan-phase2.md` — §2e playbook, §1 exclusion register.

## Unomi-specific never

- **Never** replace `master` review refactors with 3-dev monoliths (REST mappers, tracing lifecycle, test harness, shell CRUD fixes).
- **Never** port items in plan §1 exclusion register: REST exception mappers (implement on master patterns), migration scripts (UNOMI-943), security WIP, wholesale 3-dev test harness.
- **Never** wholesale-checkout `.github/workflows` (master ahead: #780, #957), `AGENTS.md` (#769), migration groovy, `.asf.yaml` rulesets.

## Unomi-specific always

- Check merged Phase 2 PRs (#771–#783, #755, #763, etc.) before assuming master lacks a 3-dev feature.
- **MERGE surgically:** `build.sh`, root `pom.xml`, CI — keep master non-interactive CI, Javadoc, IT memory sampler (#780, #957).
- **Docker compose:** additive only (`container_name`, debug ports); **keep** master OpenSearch/ES image pins (3-dev had 3.4.0 regressions vs master 3.0.0).

## Shell CRUD (PR J) — learned 2026-06-10

Shell CSV/table polish from 3-dev is **mostly already on master** (#755, #763). Remaining 3-dev shell diffs often **revert** review fixes (`UndeployDefinition`, `ConsentCrudCommand`, `ApiKeyCrudCommand`, `RuleCrudCommand`, docker pins). Port only:

- New classes (`DistributionCompleter`)
- Additive CLI flags (`Setup --show`, `@Completion`) on top of master defaults

**PR 1 incident:** `git log origin/unomi-3-dev..origin/master -- tools/shell-dev-commands/` would have flagged #755/#763 before blind checkout reverted ~20 fixes.

## Per–mega-PR risk (plan §2e)

| PR | Extra risk |
|---|---|
| **2** (V+U) | Wrong feature name breaks Karaf boot — diff `feature.xml` vs master names |
| **3** (L–P) | Security + persistence — never replace mappers/tracing |
| **4** (F3–F4) | Extend master `AbstractRestExceptionMapper`; do not copy 3-dev monoliths |
| **5** (K) | Router only — never bundle; never blind-checkout `extensions/router/**` |

## Validation before PR (Unomi)

Run generic checklist from `branch-backport.mdc`, plus:

- `./build.sh --help`
- `mvn -pl <affected-modules> -am compile -DskipTests`
- PR description: “master-first backport; branch-backport + §2e history/diff audit run”
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ rest/.miredot-offline.json
itests/src/main
dependency_tree.txt
.mvn/.develocity/develocity-workspace-id
/.cursor/
# Cursor IDE — commit shared agent rules; ignore local IDE state
/.cursor/*
!/.cursor/rules/
!/.cursor/rules/**
/.claude/
/.local-notes/
itests/snapshots_repository/
Expand Down
43 changes: 43 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,46 @@ Security model: [SECURITY.md](./SECURITY.md)

Agents that scan this repository should consult `SECURITY.md` and the
threat model it links before reporting issues.

## Branch backporting (generic)

When porting changes **from a source branch to a target branch**, follow
`.cursor/rules/branch-backport.mdc`. Summary:

1. **Target is canonical** for files that already exist there — branch from
`origin/<target>`, not from source.
2. **Target may be ahead** — merged review PRs on the target often improve
code beyond the source. A diff ≠ missing feature.
3. **Commit history on the target** — for each existing file:
`git log origin/<source>..origin/<target> -- <path>`. Non-empty output
means target-only fixes you must not drop.
4. **Never blind-checkout** existing files from source
(`git checkout origin/<source> -- <path>`). Port additive hunks only.
5. **Audit before commit** — diff regression scan plus history cross-check;
use `git blame origin/<target>` on any line you remove.
6. **Classify paths:** ADD (new on target) · MODIFY (hand-merge from
target) · MERGE (build/CI/deps — target wins on target-only lines).
7. **Do not** bulk-cherry-pick from source branch history without
per-commit review.

Cursor rule: `.cursor/rules/branch-backport.mdc`

## Backporting `unomi-3-dev` → `master` (UNOMI-875)

Active Phase 2 epic. **Apply generic rules above first**, then
`.cursor/rules/unomi-3-dev-backport.mdc` for Unomi-specific exclusions and
mega-PR risks.

| | |
|---|---|
| Source | `unomi-3-dev` |
| Target | `master` |
| Local plan | `.local-notes/unomi-3-dev-backport-plan-phase2.md` (git-ignored) |

Unomi-specific reminders:

- Master is ahead on REST mappers, tracing, shell CRUD (#755, #763), CI
(#780, #957), docker image pins — do not revert.
- Safe wholesale adds: new scripts, Postman, docs, new Java classes.
- Do not port: migration scripts (UNOMI-943), 3-dev REST mappers, security
WIP, wholesale test harness from 3-dev.
Loading
Loading