blob: ccbb51c8973971ada69da9ee01059bfff1ddd1be [file] [view]
<!-- 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.