<!-- SPDX-License-Identifier: Apache-2.0
     https://www.apache.org/licenses/LICENSE-2.0 -->

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [Agentic overrides — modifying framework workflows in an adopter](#agentic-overrides--modifying-framework-workflows-in-an-adopter)
  - [Override surfaces — two directories, one lookup chain](#override-surfaces--two-directories-one-lookup-chain)
    - [Adoption and `.gitignore`](#adoption-and-gitignore)
  - [What an override file may contain](#what-an-override-file-may-contain)
    - [Skip a step](#skip-a-step)
    - [Replace a step](#replace-a-step)
    - [Add a step](#add-a-step)
    - [Pre-empt a decision-table row](#pre-empt-a-decision-table-row)
  - [What an override file should explain](#what-an-override-file-should-explain)
  - [How a framework skill consults overrides](#how-a-framework-skill-consults-overrides)
  - [Hard rules](#hard-rules)
  - [Reconciliation on framework upgrade](#reconciliation-on-framework-upgrade)
  - [Upstreaming an override](#upstreaming-an-override)
  - [Why agentic, not declarative?](#why-agentic-not-declarative)
  - [Cross-references](#cross-references)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

<!-- SPDX-License-Identifier: Apache-2.0
     https://www.apache.org/legal/release-policy.html -->

# Agentic overrides — modifying framework workflows in an adopter

The framework's skills are project-agnostic by design. An
adopter project that needs to modify a framework workflow's
behaviour — different defaults, an extra step, a skipped step,
a different tone — does **not** fork the framework, does **not**
modify the framework's snapshot in `.apache-magpie/`, and does
**not** copy a framework skill into their own
`.claude/skills/`. Instead, they write an **override file**:
agent-readable markdown that the framework skill consults at
run-time and applies before executing default behaviour.

This document is the **contract** between adopter authors of
override files and framework authors of skills that read them.

## Override surfaces — two directories, one lookup chain

Framework skills consult **two** override directories in precedence
order, first hit wins:

1. **`.apache-magpie-local/<skill>.md`** — personal, gitignored.
   Per-developer preferences (local clone paths, a release manager
   enabling an extra MCP, wording adjustments) that should not be
   committed to the shared repo.  Never committed; never pushed.
   Works on a repo that has not yet adopted Magpie — the user adds
   one `.gitignore` line by hand so the directory stays untracked,
   then drops their overrides there.  The same additive-only
   guardrail applies: it cannot weaken the safety, confidentiality,
   or privacy baseline.

2. **`.apache-magpie-overrides/<skill>.md`** — committed,
   project-wide.  Shared modifications every contributor on the
   project sees (custom steps, project-specific defaults, integrations
   with project tooling).

```text
<adopter-repo>/
├── .apache-magpie-local/                (gitignored, per-person)
│   └── <framework-skill-name>.md       (e.g. pr-management-triage.md)
├── .apache-magpie-overrides/            (committed, project-wide)
│   ├── README.md                        (scaffolded by /magpie-setup adopt)
│   ├── <framework-skill-name>.md
│   └── <other-framework-skill-name>.md
```

When both directories contain a file for the same skill, the
personal-local file wins — its instructions are applied first,
then (by default) the committed file's instructions are also applied
unless the personal file explicitly says to skip it.  Neither file
is required to exist; a skill that finds neither proceeds with
framework defaults.

### Adoption and `.gitignore`

`/magpie-setup adopt` adds `/.apache-magpie-local/` to the adopter
repo's `.gitignore` automatically.  On a repo that has not adopted
Magpie, add the line manually:

```text
/.apache-magpie-local/
```

## What an override file may contain

Free-form agent-readable markdown. The agent interprets it. No
templating engine, no patch tool, no DSL. The override author
writes what they want to change, and the framework skill applies
it on every invocation.

Common shapes:

### Skip a step

```markdown
### Override 1 — Skip the workflow-approval auto-approve

For first-time-contributor PRs, the default flow approves the
workflow run automatically after diff inspection. Skip that
step entirely; we approve workflow runs by hand on this repo.
```

### Replace a step

```markdown
### Override 2 — Replace the close-comment template

Replace the body the `close` action posts with the project-
specific wording in
[`<adopter-repo>/.github/CONTRIBUTING-pr-quality.md`](../.github/CONTRIBUTING-pr-quality.md)
section *"PRs we close as out of scope"*. Keep the AI-attribution
footer.
```

### Add a step

```markdown
### Override 3 — Always tag @core-maintainers on first comment

Before posting any comment on a PR for the first time, add a
`@apache/airflow-core-maintainers` mention so the team gets a
notification. Do not add it on subsequent comments on the same
PR.
```

### Pre-empt a decision-table row

```markdown
### Override 4 — Treat backport PRs as already-triaged

Any PR whose base branch matches `v[0-9]-[0-9]-test` is
auto-classified as `already-triaged` regardless of triage
markers. Skip the `mark-ready` action; backports go straight to
the `pr-management-code-review` queue when their CI passes.
```

## What an override file should explain

Every override file should answer two questions for a future
maintainer (or a future agent on a later run):

1. **Why does this adopter need to deviate from the
   framework's default?** Often the answer is a project-
   specific convention, an existing tool the framework
   doesn't know about, or a deliberate softer/harder stance
   on a default policy.
2. **Should this be upstreamed?** If the override is widely
   useful, it belongs in the framework. The override file
   says so explicitly, and the next person running the
   `/magpie-setup override <skill>` flow takes the cue and
   opens a PR against `apache/magpie`.

## How a framework skill consults overrides

Every framework skill that supports overrides starts each
invocation with this opening protocol:

1. Read `<adopter-repo>/.apache-magpie-local/<this-skill>.md`
   (personal, gitignored) if it exists.
2. Read `<adopter-repo>/.apache-magpie-overrides/<this-skill>.md`
   (committed, project-wide) if it exists.
3. Surface the titles and override headlines
   (`### Override N — ...`) from both files to the user
   before doing anything else.  Indicate which file each
   came from so the user can tell personal from shared
   overrides at a glance.
4. Apply both sets of overrides: personal-local first, then
   committed.  Each `### Override N — ...` section modifies
   the skill's default behaviour for this run.  The agent
   interprets the instructions and adjusts the rest of the
   skill's flow accordingly.
5. After the skill finishes, recap which overrides were
   applied (source file + override headline), and any the
   agent decided not to apply with the reasoning, so the user
   has an audit trail.

A skill that does **not** yet support overrides documents
that explicitly in its `SKILL.md`. The
[`setup override`](../../skills/setup/overrides.md)
sub-action surfaces this gap and suggests opening a
framework-side issue requesting the hook.

## Hard rules

These are baked into agent instructions across the framework.
A framework agent NEVER:

- Modifies the snapshot under
  `<adopter-repo>/.apache-magpie/`. The snapshot is a build
  artefact — every modification gets blown away on the next
  `/magpie-setup upgrade`. Local mods go into
  `.apache-magpie-local/` (personal) or
  `.apache-magpie-overrides/` (shared).
- Commits or pushes `.apache-magpie-local/` content. The
  personal override directory is gitignored by design — it
  carries per-person paths, credentials, and capability
  enablements the contributor has not chosen to share.
- Proposes overrides be merged in by editing the framework
  source in the snapshot. Framework changes go via PR to
  `apache/magpie`.
- Auto-rewrites override files on framework upgrades. When
  a framework upgrade restructures a skill that has an
  override, the agent surfaces the conflict and lets the
  human decide (the override expresses adopter intent —
  re-anchoring it correctly is human judgement, not
  pattern-matching).
- Weakens the safety, confidentiality, or privacy baseline
  from either override surface.  An override that attempts
  to do so is ignored and the conflict is surfaced.

## Reconciliation on framework upgrade

When `/magpie-setup upgrade` refreshes the snapshot, it
walks every override file and surfaces:

- Overrides whose target framework skill no longer exists
  (renamed or removed).
- Overrides that reference framework structure (step
  numbers, golden rules, decision-table rows) that has
  changed in the new framework version.

Both are surfaced as ⚠ — non-blocking, but the user re-
anchors the override against the new framework structure
before relying on it again. Until re-anchored, the framework
skill applies what it can interpret from the override and
reports anything it skipped.

## Upstreaming an override

If an adopter project's override is widely useful (e.g. a
behaviour the framework should ship by default for all
adopters), the right move is **a PR against the framework**:

1. Read the latest `apache/magpie` `main`.
2. Implement the change in the framework skill's source.
3. Open the PR.
4. Once merged, the next `/magpie-setup upgrade` in the
   adopter pulls the framework change.
5. The adopter's now-redundant override gets deleted.

The
[`setup override`](../../skills/setup/overrides.md)
sub-action prompts the user about upstreaming on every
override scaffold; the
[`security-issue-fix`](../../skills/security-issue-fix/SKILL.md)
and
[`pr-management-code-review`](../../skills/pr-management-code-review/SKILL.md)
skills know how to open a public PR — point them at the
framework repo.

## Why agentic, not declarative?

The first cut of an override mechanism would be templated:
a YAML schema, declared anchors per skill step, a runtime
patch. We deliberately rejected that:

- **Schemas drift.** Every framework restructure breaks
  every adopter's overrides. The framework's authors have
  to maintain backward-compatible anchor tags forever, or
  every upgrade is a synchronised override-rewrite event
  across every adopter.
- **Schemas force pre-thought.** The framework would have
  to anticipate every override an adopter might want and
  surface anchors for it. The agentic mechanism inverts
  this: adopters describe what they want, the agent figures
  out how to apply it against whatever shape the framework
  currently has. The framework is free to restructure;
  overrides are free to express intent in whatever
  granularity the user finds natural.
- **Agents already interpret natural-language workflow
  changes**. The whole framework is agent-readable
  markdown — having overrides be the same lets the agent
  apply them with the same comprehension primitives as
  the underlying skills.

Trade-off: agentic interpretation has variance. An override
that says "always tag @core-maintainers" might be applied
slightly differently across runs. The mechanism mitigates
this by:

1. Surfacing override application *before* skill execution
   so the user can correct ambiguity.
2. Recapping override application *after* skill execution
   for audit.
3. Keeping override files small and specific (the
   `/magpie-setup override` flow encourages one focused
   override per file, not a sprawling rewrite).

## Cross-references

- [`setup` skill](../../skills/setup/SKILL.md) — the entry point
  that manages the snapshot, scaffolds overrides, and adds the
  `.gitignore` entries for both override directories.
- [`overrides.md` sub-action](../../skills/setup/overrides.md) —
  interactive override creation (lets the user choose between the
  personal-local and committed surfaces).
- [Top-level README](../../README.md) — adoption flow.
- [`setup-status` skill](../../skills/setup-status/SKILL.md) —
  the adoption dashboard, which reports whether both override
  directories are present.
