Skip to content
Draft
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
71 changes: 71 additions & 0 deletions .github/agents/migrate-to-merge-props-batch.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
name: migrate-to-merge-props-batch
description: Performs one bounded ADR-025 mergeProps migration batch and returns validation and migration-report evidence to the coordinator.
tools:
- read
- search
- edit
- execute
skills:
- migrate-to-merge-props
- style-guide
- changesets
- storybook
---

You implement exactly one batch assigned by the `migrate-to-merge-props`
coordinator. Use that skill for the ADR, validated patterns, scope, stack
contract, and validation requirements.

## Required input

Do not begin without:

- The current stack branch.
- Exact component names, file paths, and report locations.
- The maximum batch size.
- Total and affected-file counts before the batch.
- Targeted validation commands.

Confirm the branch and findings still match the assignment. Stop if the batch
is too large, overlaps another entry, includes unassigned files, or requires an
unresolved architecture, accessibility, or public API decision.

## Workflow

1. Read ADR-025, the repository instructions, `mergeProps`, its tests, and any
relevant migrated component from a lower batch entry.
2. Confirm every assigned finding still appears in the report.
3. Inspect public props, spread order, handlers, styles, class names, refs,
invariant attributes, tests, stories, and nearby prior art.
4. Implement only the assigned findings and tightly coupled tests, type tests,
or changesets.
5. Pass component props first and consumer props second.
6. Keep component class names as strings.
7. Omit absent optional consumer handlers from the second argument.
8. Compose refs separately.
9. Omit or gate invariant attributes in public types and apply them after the
merged spread.
10. Format, lint, test, type-check, and run any requested Storybook,
accessibility, visual, or build validation.
11. Regenerate the report and confirm the assigned findings disappeared with
no new findings.

Do not disable enforcement, add blanket suppressions, manipulate report output,
expose `mergeProps` publicly, fix unrelated findings, select another batch,
create stack entries, commit, or change stack structure. Do not refine the
adoption rule, report, utility, workflow, coordinator, or agent in a batch
entry. Return those issues as blockers so the coordinator can update the owning
lower stack entry and rebase.

## Result format

| Field | Content |
| ------------- | -------------------------------------------------------------------- |
| Branch | Current stack branch |
| Assigned | Component names, paths, and original locations |
| Resolved | Findings removed from the regenerated report |
| Files changed | Source, tests, types, stories, and changesets edited |
| Remaining | Updated finding and affected-file counts |
| Validation | Failed commands and relevant summaries, or `Passed` |
| Blockers | Findings requiring an ADR, API, accessibility, or ownership decision |
240 changes: 240 additions & 0 deletions .github/skills/migrate-to-merge-props/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
---
name: migrate-to-merge-props
description: 'Use when: coordinating ADR-025 adoption through measured mergeProps batches in a stacked migration. Plans bounded batches, invokes migrate-to-merge-props-batch, verifies report progress, and removes temporary migration tooling at completion.'
---

# Migrate to mergeProps

Coordinate adoption of
[`ADR-025: Prop merging conventions`](../../../contributor-docs/adrs/adr-025-prop-merging.md).

ADR-025 is the source of truth for correctness. The ESLint rule and migration
report identify likely work, but a finding is not complete until the component
preserves its behavior, accessibility contract, public types, refs, handlers,
class names, and styles according to the ADR.

## Sources of truth and migration artifacts

| Artifact | Location | Role | Lifetime |
| ----------------- | ------------------------------------------------------------------------------------- | ----------------------------------------- | --------- |
| ADR | `contributor-docs/adrs/adr-025-prop-merging.md` | Defines the target prop-merging contract | Permanent |
| Style guidance | `contributor-docs/style.md`, "Merge shared props intentionally" | Shows the component-authoring convention | Permanent |
| Utility | `packages/react/src/utils/mergeProps.ts` | Implements shared merge behavior | Permanent |
| Adoption rule | `primer/prefer-merge-props` in `packages/eslint-config/src/rules/preferMergeProps.ts` | Detects unmerged component root props | Permanent |
| Migration report | `node script/merge-props-migration-status.mts` | Measures remaining findings | Temporary |
| Batch agent | `.github/agents/migrate-to-merge-props-batch.agent.md` | Implements one assigned migration batch | Temporary |
| Coordinator skill | `.github/skills/migrate-to-merge-props/SKILL.md` | Plans, delegates, measures, and cleans up | Temporary |

## Scope

- Included: findings reported in `packages/react/src/**/*.{ts,tsx}` by
`primer/prefer-merge-props`.
- Excluded: tests, stories, nested JSX, generated output, `.agents/**/*`, and
pure pass-through roots that have one spread and no component-authored prop
other than `ref` or `key`.
- Refs are always composed separately with `useMergedRefs`.
- Default maximum batch size: five findings.
- Default run size: two sequential batches per invocation.
- Never split one source file across separate batches.

## Migration rules and prior art

Before the first implementation batch, inspect:

- The component example in `contributor-docs/style.md`.
- `packages/react/src/utils/mergeProps.ts`.
- `packages/react/src/utils/__tests__/mergeProps.test.ts`.

After implementation batches exist, inspect a relevant migrated component from
a lower stack entry as prior art. Do not add reference component migrations to
the driver entry.

Apply these rules:

1. Pass component-authored props first and consumer-authored props second.
2. Keep the component-authored `className` as a string. Let `mergeProps` use
`clsx` to combine it with consumer class values.
3. Do not add an optional consumer handler to the second argument when it is
absent. An explicit `undefined` entry would replace the internal handler
instead of composing it.
4. Keep refs outside `mergeProps`.
5. Put invariant attributes after the merged spread and omit them from the
public prop type. Use a discriminated union when ownership depends on the
rendered element.
6. Preserve intentional consumer `undefined` precedence for ordinary props.
7. Add tests for event order, cancellation, controlled attributes, type
exclusions, or other behavior that is not already covered.

## Stack ownership contract

Every change must live in the entry that owns its concern:

- `copilot/update-style-docs-prop-merging` owns ADR-025, `mergeProps`, the
adoption rule, rule tests, report script, and migration-status workflow.
Refinements to any of those artifacts must be committed to this foundation
entry.
- `migrate/merge-props-migrator` owns only the coordinator skill and batch
agent. It must not contain component migrations, migration changesets, or
adoption-tool refinements.
- `migrate/merge-props-batch-NN` owns only its assigned component
implementation, tightly coupled tests or stories, and required changesets.
- `migrate/merge-props-cleanup` owns final temporary-artifact removal and the
ADR status update.

If batch work exposes a problem in the adoption rule, report, utility, or
workflow:

1. Stop the batch without working around the problem.
2. Navigate to `copilot/update-style-docs-prop-merging`.
3. Commit the refinement there.
4. Rebase every upstack entry.
5. Regenerate the report before resuming the batch.

If the coordinator or agent instructions need refinement, update
`migrate/merge-props-migrator` and rebase the batch entries above it.

## Stack contract

Use one linear stack:

1. `copilot/update-style-docs-prop-merging`: ADR, utility, adoption mechanism,
report, workflow, and all refinements to those artifacts.
2. `migrate/merge-props-migrator`: coordinator skill and batch agent only.
3. `migrate/merge-props-batch-01` through
`migrate/merge-props-batch-NN`: one bounded component implementation batch
per entry.
4. `migrate/merge-props-cleanup`: temporary artifact removal after the report
reaches zero.

Use only non-interactive stack commands:

```shell
gh stack view --json
gh stack add migrate/merge-props-batch-NN
gh stack submit --auto
```

Do not create the cleanup entry while in-scope findings remain.

## Coordinator workflow

### 1. Resume the stack

Inspect:

```shell
git status --short --branch
gh stack view --json
```

Confirm the current branch is the top active entry. If a lower entry changed,
rebase the upstack before selecting findings. Do not mix unrelated worktree
changes into a migration entry.

Inspect the diff for each existing stack entry and confirm it still follows the
stack ownership contract before creating another batch.

### 2. Establish the baseline

Run:

```shell
node script/merge-props-migration-status.mts
```

Record the total finding count, affected-file count, exact paths and locations,
findings already assigned to stack entries, and blockers. Do not edit generated
output or exclusions to lower the count.

### 3. Plan non-overlapping batches

Group findings by component family and remediation pattern. Each batch must:

- Contain at most the selected finding limit.
- Own complete files rather than splitting a file between entries.
- Be reviewable as one coherent change.
- Avoid files already assigned to an existing stack entry.
- Include tightly coupled tests and changesets.

Calculate the remaining batch count using the selected limit.

### 4. Ask how much work to run

Use a structured prompt containing:

| Field | Default | Constraint |
| ----------- | ------- | ---------------------------------------- |
| Batch size | `5` | Integer greater than or equal to `1` |
| Run mode | Limited | Limited batches or all remaining batches |
| Batch count | `2` | Integer greater than or equal to `1` |

Show the baseline, calculated remaining batches, and exact assignments before
editing. Prefer a small set of sequential batches over running the full
migration at once.

### 5. Run each selected batch

For each batch:

1. Create `migrate/merge-props-batch-NN` with `gh stack add`.
2. Invoke `migrate-to-merge-props-batch` with the branch, exact paths and
locations, maximum size, before counts, and targeted validation commands.
3. Review the returned diff and evidence.
4. Add or update changesets for consumer-facing behavior or type changes.
5. Confirm the entry contains no adoption-tool or driver changes.
6. Commit only the assigned batch.
7. Regenerate the report.
8. Confirm assigned findings disappeared, no new findings appeared, and counts
changed by the expected amount.
9. Stop before another entry if validation or report evidence fails.

Run code-editing batch agents sequentially because every branch depends on the
previous branch.

### 6. Handle blockers

Do not force a mechanical merge when a finding requires a decision about:

- Consumer veto before internal behavior.
- Whether an ARIA, semantic, or stable identifier prop is component-owned.
- A breaking public type change.
- Polymorphic attribute ownership.
- Ref composition.

Return the file, component, current behavior, ADR conflict, and smallest
decision needed.

### 7. Finish or pause

In limited mode, stop after the selected number of entries and leave the stack
resumable.

When the report reaches zero, add `migrate/merge-props-cleanup` and remove:

- `.github/skills/migrate-to-merge-props/`
- `.github/agents/migrate-to-merge-props-batch.agent.md`
- `script/merge-props-migration-status.mts`
- The `merge-props` job from `.github/workflows/migration-status.yml`

Keep ADR-025, style guidance, `mergeProps`, the ESLint rule, and regression
tests. Mark ADR-025 adopted and implemented in the cleanup entry after final
validation.

### 8. Submit and report

Run:

```shell
gh stack submit --auto
gh stack view --json
```

Return completed stack entries, requested/completed/remaining batches, resolved
paths, updated counts, validation failures, and blockers. Do not claim
completion before the report is zero and the cleanup entry exists.

## Example invocation

> Use `/migrate-to-merge-props` with at most five findings per entry. Run two
> batches, regenerate the report after each entry, and stop on unexpected
> results.
Loading