|
| 1 | +--- |
| 2 | +name: setup-override-upstream |
| 3 | +description: | |
| 4 | + Walk an adopter through promoting a local |
| 5 | + `.apache-steward-overrides/<skill>.md` file into a PR |
| 6 | + against `apache/airflow-steward`. Lists the adopter's |
| 7 | + overrides, helps the user pick one, reads it alongside the |
| 8 | + framework skill it modifies, helps decide whether the |
| 9 | + change is generalisable (some overrides encode project- |
| 10 | + specific decisions and should stay local), designs the |
| 11 | + framework-level abstraction (configurable parameter, |
| 12 | + optional step, changed default, etc.), implements it in |
| 13 | + the user's local apache-steward clone, runs the |
| 14 | + framework's pre-commit, and opens the PR. After the PR |
| 15 | + merges and the adopter runs `/setup-steward upgrade`, the |
| 16 | + override file in the adopter repo is no longer needed and |
| 17 | + the skill prompts for its removal. |
| 18 | +when_to_use: | |
| 19 | + Invoke when the user says "upstream my override", "promote |
| 20 | + this override to the framework", "convert my local |
| 21 | + modification into a steward feature", "make this override |
| 22 | + a framework feature", "open a PR to apache-steward for |
| 23 | + this override", or similar — typically after running the |
| 24 | + override locally for a while and deciding the change is |
| 25 | + worth contributing back. |
| 26 | +license: Apache-2.0 |
| 27 | +--- |
| 28 | + |
| 29 | +<!-- SPDX-License-Identifier: Apache-2.0 |
| 30 | + https://www.apache.org/legal/release-policy.html --> |
| 31 | + |
| 32 | +<!-- Placeholder convention (see ../../AGENTS.md#placeholder-convention-used-in-skill-files): |
| 33 | + <adopter-repo> → repo this skill is being run in (an adopter) |
| 34 | + <override-file> → .apache-steward-overrides/<skill>.md being upstreamed |
| 35 | + <framework-skill> → framework skill the override modifies |
| 36 | + <framework-clone> → user's local clone of apache/airflow-steward |
| 37 | + (separate from .apache-steward/, which is a gitignored snapshot) |
| 38 | + <framework-fork> → user's GitHub fork of apache/airflow-steward |
| 39 | + (where the PR branch gets pushed) --> |
| 40 | + |
| 41 | +# setup-override-upstream |
| 42 | + |
| 43 | +This skill is the path from *local override* to *framework |
| 44 | +feature*. It takes a single |
| 45 | +`.apache-steward-overrides/<skill>.md` file in an adopter |
| 46 | +repo, walks the user through deciding whether the change is |
| 47 | +worth upstreaming, designs the framework-level abstraction, |
| 48 | +implements it in `apache/airflow-steward`, and opens a PR. |
| 49 | + |
| 50 | +The override mechanism (per |
| 51 | +[`docs/setup/agentic-overrides.md`](../../../docs/setup/agentic-overrides.md)) |
| 52 | +is deliberately *agentic* and *adopter-local*: there's no |
| 53 | +schema, no anchors, no patch tool. That makes overrides |
| 54 | +quick to write but hard to share — every adopter who wants |
| 55 | +the same behaviour writes their own. **Upstreaming** is the |
| 56 | +escape hatch: when an override stops being project-specific |
| 57 | +and starts looking like a missing feature, the right move |
| 58 | +is a PR that bakes the change into the framework's default, |
| 59 | +making every adopter benefit on their next |
| 60 | +`/setup-steward upgrade`. |
| 61 | + |
| 62 | +## Adopter overrides |
| 63 | + |
| 64 | +Before running the default behaviour documented below, this |
| 65 | +skill consults |
| 66 | +[`.apache-steward-overrides/setup-override-upstream.md`](../../../docs/setup/agentic-overrides.md) |
| 67 | +in the adopter repo if it exists, and applies any |
| 68 | +agent-readable overrides it finds. See |
| 69 | +[`docs/setup/agentic-overrides.md`](../../../docs/setup/agentic-overrides.md) |
| 70 | +for the contract — what overrides may contain, hard rules, |
| 71 | +the reconciliation flow on framework upgrade, upstreaming |
| 72 | +guidance. |
| 73 | + |
| 74 | +**Hard rule**: agents NEVER modify the snapshot under |
| 75 | +`<adopter-repo>/.apache-steward/`. Local modifications go in |
| 76 | +the override file. Framework changes go via PR to |
| 77 | +`apache/airflow-steward`. |
| 78 | + |
| 79 | +--- |
| 80 | + |
| 81 | +## Snapshot drift |
| 82 | + |
| 83 | +Also at the top of every run, this skill compares the |
| 84 | +gitignored `.apache-steward.local.lock` (per-machine |
| 85 | +fetch) against the committed `.apache-steward.lock` (the |
| 86 | +project pin). On mismatch the skill surfaces the gap and |
| 87 | +proposes |
| 88 | +[`/setup-steward upgrade`](../setup-steward/upgrade.md). |
| 89 | +The proposal is non-blocking — the user may defer if |
| 90 | +they want to run with the local snapshot for now. See |
| 91 | +[`docs/setup/install-recipes.md` § Subsequent runs and drift detection](../../../docs/setup/install-recipes.md#subsequent-runs-and-drift-detection) |
| 92 | +for the full flow. |
| 93 | + |
| 94 | +Drift severity: |
| 95 | + |
| 96 | +- **method or URL differ** → ✗ full re-install needed. |
| 97 | +- **ref differs** (project bumped tag, or `git-branch` |
| 98 | + local is behind upstream tip) → ⚠ sync needed. |
| 99 | +- **`svn-zip` SHA-512 mismatches the committed |
| 100 | + anchor** → ✗ security-flagged; investigate before |
| 101 | + upgrading. |
| 102 | + |
| 103 | +> **Doubly important here**: the skill is about to design |
| 104 | +> a framework-level abstraction by reading the snapshot's |
| 105 | +> framework skill. If the snapshot is stale, the |
| 106 | +> abstraction may be designed against a version that has |
| 107 | +> already changed upstream. Address drift before |
| 108 | +> proceeding. |
| 109 | +
|
| 110 | +--- |
| 111 | + |
| 112 | +## Golden rules |
| 113 | + |
| 114 | +**Golden rule 1 — not every override should be upstreamed.** |
| 115 | +Many overrides encode genuinely *project-specific* choices: |
| 116 | +the wording of a canned response, the project's scope-label |
| 117 | +taxonomy, milestone-format regex, a tone-of-voice |
| 118 | +preference. These should stay in the adopter repo. The |
| 119 | +skill explicitly walks through this decision and stops |
| 120 | +early if the change is not generalisable. |
| 121 | + |
| 122 | +**Golden rule 2 — write to `<framework-clone>`, never to |
| 123 | +the snapshot.** The framework PR is implemented in the |
| 124 | +user's local apache-steward clone (a separate working |
| 125 | +directory from the adopter's `.apache-steward/` snapshot, |
| 126 | +which is gitignored and read-only). If the user does not |
| 127 | +have a clone yet, the skill helps them set one up. |
| 128 | + |
| 129 | +**Golden rule 3 — assistant proposes, user fires.** Per the |
| 130 | +framework convention (see |
| 131 | +[`AGENTS.md`](../../../AGENTS.md)), every state-changing |
| 132 | +action — clone, branch, commit, push, `gh pr create` — is |
| 133 | +proposed by the skill and only happens on explicit user |
| 134 | +confirmation. Public PR content is shown to the user before |
| 135 | +it is posted. |
| 136 | + |
| 137 | +**Golden rule 4 — decouple PR from override deletion.** |
| 138 | +Opening the framework PR is one step; deleting the now- |
| 139 | +redundant override file in the adopter repo is a separate |
| 140 | +step that happens AFTER the PR has merged AND the adopter |
| 141 | +has run `/setup-steward upgrade` to pick up the framework |
| 142 | +change. The skill ends with a clear pointer at the |
| 143 | +post-merge cleanup; it does not delete the override |
| 144 | +preemptively. |
| 145 | + |
| 146 | +## Walk-through |
| 147 | + |
| 148 | +### Step 0 — Pre-flight |
| 149 | + |
| 150 | +1. We are in an adopter repo (has |
| 151 | + `<adopter-repo>/.apache-steward.lock` and |
| 152 | + `<adopter-repo>/.apache-steward-overrides/`). If not, |
| 153 | + stop — the skill is for adopters with at least one |
| 154 | + override file. |
| 155 | +2. The snapshot is current (no drift per the section |
| 156 | + above). If drift exists, propose |
| 157 | + `/setup-steward upgrade` first. |
| 158 | +3. Identify `<framework-clone>` — the user's local clone |
| 159 | + of `apache/airflow-steward`. Common locations: |
| 160 | + `~/code/airflow-steward/`, `~/work/airflow-steward/`. |
| 161 | + If not found, surface and ask the user where it is, or |
| 162 | + help them clone it (`git clone |
| 163 | + git@github.com:apache/airflow-steward.git`). The clone |
| 164 | + is **separate** from `<adopter-repo>/.apache-steward/` |
| 165 | + (the snapshot). |
| 166 | + |
| 167 | +### Step 1 — Pick the override |
| 168 | + |
| 169 | +List `<adopter-repo>/.apache-steward-overrides/*.md` |
| 170 | +(excluding the directory's own `README.md`). For each, |
| 171 | +print the file name + first headline. |
| 172 | + |
| 173 | +- **Zero overrides** → stop. There is nothing to upstream. |
| 174 | +- **One override** → auto-pick. |
| 175 | +- **Multiple** → ask the user which one to upstream this |
| 176 | + run. The skill handles one override per invocation |
| 177 | + (clean PR, clean review). |
| 178 | + |
| 179 | +### Step 2 — Read the override + framework skill |
| 180 | + |
| 181 | +Read the chosen override file. Surface to the user: |
| 182 | + |
| 183 | +- Title + the override headlines (`### Override N — ...`) |
| 184 | +- The "why" paragraph if the file has one |
| 185 | + |
| 186 | +Then read the framework skill it modifies, from the |
| 187 | +snapshot at |
| 188 | +`<adopter-repo>/.apache-steward/.claude/skills/<framework-skill>/`. |
| 189 | +Surface: |
| 190 | + |
| 191 | +- The skill's purpose (frontmatter description) |
| 192 | +- The specific section(s) the override modifies (steps, |
| 193 | + decision-table rows, golden rules) |
| 194 | +- Any cross-skill references the override depends on |
| 195 | + |
| 196 | +Goal: both the user and the agent should now have a clear |
| 197 | +mental model of *what* the change is and *where* it |
| 198 | +applies. |
| 199 | + |
| 200 | +### Step 3 — Decide if upstreamable |
| 201 | + |
| 202 | +Walk through with the user. Common categories: |
| 203 | + |
| 204 | +- **Project-specific** (canned-response wording, scope |
| 205 | + labels, milestone formats, tooling assumptions |
| 206 | + particular to this project) → **stop here**. Suggest the |
| 207 | + override stay local. Generalising would require the |
| 208 | + framework to either include the adopter's specifics |
| 209 | + (defeats project-agnosticism) or expose a config knob |
| 210 | + that no other adopter would set the same way (bloats the |
| 211 | + contract). |
| 212 | +- **Missing feature** (the override does something useful |
| 213 | + that any adopter might want) → **continue**. The |
| 214 | + framework should learn this behaviour by default, or |
| 215 | + expose it as an opt-in. |
| 216 | +- **Better default** (the override changes a default the |
| 217 | + framework currently picks; if a majority of adopters |
| 218 | + would prefer the override's default, the framework |
| 219 | + should adopt it) → **continue**. The PR may also keep |
| 220 | + the old behaviour reachable via a flag. |
| 221 | +- **Refactor a step** (the framework's step is |
| 222 | + awkward / redundant / has an edge case) → **continue**. |
| 223 | + The PR fixes the step itself. |
| 224 | + |
| 225 | +If the user is unsure, lean toward **stop** — keep the |
| 226 | +override local until a second adopter wants the same thing. |
| 227 | + |
| 228 | +### Step 4 — Design the framework-level abstraction |
| 229 | + |
| 230 | +Once the user confirms the change is upstreamable, design |
| 231 | +the framework-side change. Pick one of: |
| 232 | + |
| 233 | +| Shape | When | |
| 234 | +|---|---| |
| 235 | +| **Add a config knob** in `<project-config>/` | The change is opt-in per-adopter; default behaviour is unchanged. | |
| 236 | +| **Change a default** | The new behaviour is better for the majority; the framework's existing default becomes a `<project-config>/` opt-out. | |
| 237 | +| **Add an optional step** | The change is an *additional* step (not a substitute for an existing one). | |
| 238 | +| **Refactor existing step** | The change rewrites how an existing step works. No new config; the new behaviour is universal. | |
| 239 | + |
| 240 | +Surface the proposal to the user. Iterate. The output of |
| 241 | +this step is a concrete plan: which framework files to |
| 242 | +modify, what to add / remove / change, what tests or |
| 243 | +verification the framework already has that may need |
| 244 | +updating. |
| 245 | + |
| 246 | +### Step 5 — Implement in the framework clone |
| 247 | + |
| 248 | +In `<framework-clone>`: |
| 249 | + |
| 250 | +1. `git fetch origin && git checkout -b |
| 251 | + feat/<short-description> origin/main` |
| 252 | +2. Apply the changes the design step decided on. Read the |
| 253 | + surrounding framework code first (the framework's |
| 254 | + `AGENTS.md`, the relevant supporting files of the |
| 255 | + modified skill) to match conventions. |
| 256 | +3. Run framework pre-commit: |
| 257 | + `prek run --all-files`. Fix anything that fires. |
| 258 | +4. Show the user the diff (`git diff`). Get explicit |
| 259 | + confirmation before committing. |
| 260 | +5. Commit with a message matching the framework's |
| 261 | + conventions (Conventional-Commits prefix: |
| 262 | + `feat(skills): ...` for new framework behaviour, |
| 263 | + `refactor(skills): ...` for restructure, etc.). Use |
| 264 | + `Generated-by: Claude Code (Claude Opus 4.7)` trailer |
| 265 | + per the framework's no-coauthored-by hook. |
| 266 | + |
| 267 | +### Step 6 — Open the PR |
| 268 | + |
| 269 | +1. `git push -u <fork-remote> feat/<branch>`. If no fork |
| 270 | + remote is configured, surface and help the user add one |
| 271 | + (`git remote add fork <user>/airflow-steward.git`). |
| 272 | +2. Draft the PR title + body. Include: |
| 273 | + - **Summary** — what the change is, in 1–3 bullets. |
| 274 | + - **Motivation** — link to the originating override |
| 275 | + file in the adopter repo (the user's project), with |
| 276 | + enough context that the framework reviewer |
| 277 | + understands the use case without reading the full |
| 278 | + override. |
| 279 | + - **Migration path for existing adopters** — if the |
| 280 | + change introduces a new config knob, explain the |
| 281 | + default; if it changes a default, explain how |
| 282 | + adopters opt out. |
| 283 | + - **Test plan** — what the user verified locally. |
| 284 | +3. **Confirm with the user before posting**. Show the |
| 285 | + exact title + body. Wait for "OK to post" / "yes" / |
| 286 | + "send" / similar before running `gh pr create`. |
| 287 | +4. `gh pr create --repo apache/airflow-steward --base |
| 288 | + main --head <user>:<branch> --title "..." --body "..."` |
| 289 | + |
| 290 | +### Step 7 — Post-PR cleanup pointer |
| 291 | + |
| 292 | +After the PR is open, surface to the user: |
| 293 | + |
| 294 | +```text |
| 295 | +Framework PR opened: <PR URL> |
| 296 | +
|
| 297 | +Next steps once it merges: |
| 298 | +
|
| 299 | + 1. /setup-steward upgrade (in <adopter-repo>) |
| 300 | + - Bumps the snapshot to the new framework version. |
| 301 | + - .apache-steward.lock will reflect the new pin. |
| 302 | + 2. Delete .apache-steward-overrides/<skill>.md in <adopter-repo> |
| 303 | + - The override is now redundant; the framework does |
| 304 | + what the override used to do. |
| 305 | + 3. Commit the deletion + the bumped lock together. |
| 306 | +``` |
| 307 | + |
| 308 | +The skill **does not** delete the override file itself — |
| 309 | +that happens after the PR merges, and the skill cannot |
| 310 | +predict when (or if) the framework reviewers accept the |
| 311 | +PR. Deletion is the user's manual cleanup once the PR |
| 312 | +lands. |
| 313 | + |
| 314 | +## Output to the user (skill end) |
| 315 | + |
| 316 | +```text |
| 317 | +✓ Override picked: .apache-steward-overrides/<skill>.md |
| 318 | +✓ Framework skill: <framework-skill> |
| 319 | +✓ Decision: upstreamable as <shape from Step 4> |
| 320 | +✓ Framework clone: <framework-clone> |
| 321 | +✓ Branch: feat/<short-description> |
| 322 | +✓ Commits: <count> |
| 323 | +✓ PR opened: <PR URL> |
| 324 | +
|
| 325 | +Next: wait for the PR to merge, then in <adopter-repo>: |
| 326 | + /setup-steward upgrade |
| 327 | + rm .apache-steward-overrides/<skill>.md |
| 328 | + git add -A && git commit -m "Remove override <skill>: upstreamed in apache/airflow-steward#<N>" |
| 329 | +``` |
| 330 | + |
| 331 | +## Failure modes |
| 332 | + |
| 333 | +| Symptom | Likely cause | Remediation | |
| 334 | +|---|---|---| |
| 335 | +| `<adopter-repo>` has no `.apache-steward-overrides/` | not adopted, or adopted without the overrides scaffold | run `/setup-steward adopt` (idempotent) | |
| 336 | +| Step 1 finds zero overrides | nothing to upstream — adopter has no local modifications recorded | stop | |
| 337 | +| `<framework-clone>` not found | user has not cloned `apache/airflow-steward` yet | help them clone, then resume | |
| 338 | +| Framework pre-commit fails after the implementation | the change does not match framework conventions | iterate with the user, re-run pre-commit, do not bypass with `--no-verify` | |
| 339 | +| User decides mid-flow that the override is project-specific after all | wrong call in Step 3 | stop without opening a PR; the override file in the adopter repo is unchanged, no harm done | |
| 340 | + |
| 341 | +## What this skill is NOT for |
| 342 | + |
| 343 | +- Not for *applying* an override at run-time — that is the |
| 344 | + per-skill pre-flight protocol documented in |
| 345 | + [`docs/setup/agentic-overrides.md`](../../../docs/setup/agentic-overrides.md). |
| 346 | +- Not for *creating* a new override — that is |
| 347 | + [`/setup-steward override <skill>`](../setup-steward/overrides.md). |
| 348 | +- Not for *upgrading* the snapshot — that is |
| 349 | + [`/setup-steward upgrade`](../setup-steward/upgrade.md). |
| 350 | + Run that BEFORE this skill if drift exists. |
| 351 | +- Not for arbitrary framework PRs unrelated to overrides. |
| 352 | + This skill is specifically the override → PR flow. Other |
| 353 | + framework contributions (new skill, new tool, refactor) |
| 354 | + go through the framework's normal PR workflow. |
| 355 | + |
| 356 | +## Cross-references |
| 357 | + |
| 358 | +- [`docs/setup/agentic-overrides.md`](../../../docs/setup/agentic-overrides.md) — the override contract. |
| 359 | +- [`setup-steward/overrides.md`](../setup-steward/overrides.md) — how to *create* / *open* an override. |
| 360 | +- [`setup-steward/upgrade.md`](../setup-steward/upgrade.md) — how to upgrade the snapshot post-merge. |
0 commit comments