From f5fd128994151eb05cb750ce032362a94ae656a6 Mon Sep 17 00:00:00 2001 From: Paul Schultz Date: Tue, 3 Nov 2026 10:32:12 -0600 Subject: [PATCH 1/2] chore(agents): add agent config, ADRs, and reviewer docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add docs/agents/ (issue tracker, triage labels, domain docs) following the setup-matt-pocock-skills conventions; add an Agent skills section to AGENTS.md - Add CONTEXT.md (orientation + knowledge index) and REVIEW.md (what failure looks like here, for AI reviewers) - Record five ADRs from the commit history: Yarn 4/oxfmt toolchain, flattened recipe layout, AST-first codemods with AI fixup fallback, convention-based test runner, release-owned README/version generation - Create the five triage labels on the GitHub tracker Config and docs only — no runtime code changed. --- AGENTS.md | 14 +++++ CONTEXT.md | 32 ++++++++++++ REVIEW.md | 30 +++++++++++ docs/adr/0001-yarn4-oxfmt-toolchain.md | 20 ++++++++ docs/adr/0002-flattened-recipe-layout.md | 17 +++++++ docs/adr/0003-ast-first-ai-fixup-fallback.md | 17 +++++++ docs/adr/0004-convention-based-test-runner.md | 17 +++++++ .../0005-release-owned-readme-and-versions.md | 17 +++++++ docs/agents/domain.md | 51 +++++++++++++++++++ docs/agents/issue-tracker.md | 39 ++++++++++++++ docs/agents/triage-labels.md | 13 +++++ 11 files changed, 267 insertions(+) create mode 100644 CONTEXT.md create mode 100644 REVIEW.md create mode 100644 docs/adr/0001-yarn4-oxfmt-toolchain.md create mode 100644 docs/adr/0002-flattened-recipe-layout.md create mode 100644 docs/adr/0003-ast-first-ai-fixup-fallback.md create mode 100644 docs/adr/0004-convention-based-test-runner.md create mode 100644 docs/adr/0005-release-owned-readme-and-versions.md create mode 100644 docs/agents/domain.md create mode 100644 docs/agents/issue-tracker.md create mode 100644 docs/agents/triage-labels.md diff --git a/AGENTS.md b/AGENTS.md index 5e35de61..01ac0e3c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,6 +9,20 @@ The two failure modes most likely to bite an agent here are: Before declaring a task done, check `CONTRIBUTING.md` for the conventions in _Adding a new codemod_ (directory layout, package scope, single-quoted YAML) and run the checks listed in _Making changes_. +## Agent skills + +### Issue tracker + +GitHub Issues on `backstage/codemods` (via the `gh` CLI). See `docs/agents/issue-tracker.md`. + +### Triage labels + +Default five-label vocabulary: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `docs/agents/triage-labels.md`. + +### Domain docs + +Single-context: `GLOSSARY.md` + `docs/adr/` at the repo root (created lazily). See `docs/agents/domain.md`. + ## Planning a release migration Before implementing codemods for a new Backstage release, use the project skill [`.agents/skills/backstage-codemod-issue-research/SKILL.md`](./.agents/skills/backstage-codemod-issue-research/SKILL.md) to research breaking changes, classify codemod vs document-only items, produce an inventory table, and draft GitHub issue specs. Implementation starts only after issues are filed and approved — then use the project [`codemod` skill](./.agents/skills/codemod/SKILL.md). Pi and other Agent Skills-compatible agents can load it from `.agents/skills/`; use `npx codemod ai` for its CLI commands. diff --git a/CONTEXT.md b/CONTEXT.md new file mode 100644 index 00000000..4a8929ed --- /dev/null +++ b/CONTEXT.md @@ -0,0 +1,32 @@ +# Context + +Codemod recipes for Backstage release migrations, published to the [Codemod registry](https://codemod.com). One recipe package per Backstage release under `codemods//`, plus a misc recipe under `codemods/misc/`. Repository tooling lives in the private `packages/scripts` workspace package. + +## Layout + +``` +codemods// # one published migration-recipe package per release + scripts/.ts # transform entrypoints (js-ast-grep targets) + tests// # JSSG fixture suites + node:test suites + workflow.yaml # steps reference local scripts + codemod.yaml / package.json / README.md +codemods/misc/ # non-release recipes (mui4-to-bui) +packages/scripts/ # gates, generators, release helpers, recipe runner +docs/agents/ # agent config: tracker, triage labels, domain rules +docs/adr/ # architecture decision records +.agents/skills/ # repo skills (codemod authoring, release research) +``` + +## Where knowledge lives + +- **Contributor conventions and release flow**: [`CONTRIBUTING.md`](./CONTRIBUTING.md) — read end-to-end before opening a PR. +- **Agent pointers and failure modes**: [`AGENTS.md`](./AGENTS.md), [`REVIEW.md`](./REVIEW.md). +- **Architectural decisions and why**: [`docs/adr/`](./docs/adr/). +- **Repo skills**: [`.agents/skills/`](./.agents/skills/) — `codemod` (implementation), `backstage-codemod-issue-research` (release planning), `validate-codemod-recipe`. +- **Agent config**: [`docs/agents/`](./docs/agents/) — issue tracker, triage labels, domain docs. + +## Working rules that are easy to miss + +- Every PR that changes a codemod needs a changeset — CI does not enforce it. +- Versions in `package.json` / `codemod.yaml` are owned by Changesets and the release pipeline; never hand-edit. +- The root README is generated; it regenerates on the Version Packages PR, so codemod PRs leave it unchanged. diff --git a/REVIEW.md b/REVIEW.md new file mode 100644 index 00000000..f39276da --- /dev/null +++ b/REVIEW.md @@ -0,0 +1,30 @@ +# Review + +What failure looks like in this repo, for AI reviewers. A PR that passes CI can still be wrong in every way listed here — CI deliberately does not block on most of it. + +## Release-blocking mistakes + +- **No changeset.** A PR that changes a codemod must include `yarn changeset` output in `.changeset/`. CI will not remind anyone; without it the codemod is never tagged or published. (Docs/tooling-only PRs need none.) +- **Hand-edited versions.** `version` in `package.json` or `codemod.yaml` edited manually "to trigger a release". The Changesets bot owns both; manual edits are overwritten and cause version drift. +- **Hand-edited root README.** It is generated by `generate-readme-codemods` on the Version Packages PR. Codemod PRs leave it alone; drift is fixed on the next release PR or via `yarn readme`. + +## Recipe-structure mistakes + +- **Registry steps in `workflow.yaml`.** Every `js-ast-grep` step's `js_file` and every run step's `CODEMOD_SCRIPT` must be a local script; `codemod:` registry references are rejected by the test runner. +- **Wrong languages in `codemod.yaml`.** `targets.languages` must be the union of languages actually scanned by workflow steps (file selectors + run-step target files). Advertising a language nothing scans, or broadening selectors to match the manifest, is a bug. +- **Broken workflow-state coupling.** Steps that share state (an indexing step feeding a transform, a shell step reading state set by another) must run in the same workflow, in order. Reordering them "for tidiness" breaks the recipe. +- **Unscoped or wrong package names.** `package.json` `name` must use the `@backstage/` scope; the tagging/publishing scripts assume it. +- **Style drift in YAML.** Single quotes for string scalars in `codemod.yaml` and `workflow.yaml` (oxfmt convention); ids, type values, and booleans stay bare. + +## Cross-platform mistakes + +- **CRLF in fixtures.** Test fixtures and inputs must use LF; CRLF breaks cross-platform test comparison (a repeated failure mode in this repo's history). +- **Unbatched file lists.** Changed-file checks must batch paths (Windows argv limit), and must skip ignored test fixtures. + +## Test mistakes + +- **Ad-hoc test wiring instead of convention.** New steps don't change the test command: `scripts/.ts` + `tests///input.` fixtures are discovered automatically; `tests//assert-fixtures.ts` covers whole-app trees; `tests/**/*.test.ts` runs under `node --test`; every `tests/**/tsconfig.json` is type-checked. Adding a bespoke wrapper suite instead of following the convention is a red flag. + +## What good looks like + +`yarn format`, `yarn lint`, `yarn test` pass locally — and `yarn check:changed` reproduces exactly what CI runs, so local and remote gates cannot drift. The pre-commit (`yarn lint-staged`) and pre-push (`yarn check:changed`) hooks fail loudly rather than silently skipping. diff --git a/docs/adr/0001-yarn4-oxfmt-toolchain.md b/docs/adr/0001-yarn4-oxfmt-toolchain.md new file mode 100644 index 00000000..d34cbcc3 --- /dev/null +++ b/docs/adr/0001-yarn4-oxfmt-toolchain.md @@ -0,0 +1,20 @@ +# ADR 0001: Yarn 4 toolchain with oxfmt/oxlint and changed-file gates + +- **Status**: Accepted +- **Date**: 2026-04-16 → 2026-10-13 +- **Evidence**: `1ee5c96` (switch to Yarn), `9b9ec7d` (Corepack + Yarn 4 cache order), `933d821` (lockfile v9 under Yarn 4.14.1), `aab8333` (untrack install-state.gz), `b5e7d52` (oxfmt/oxlint/typescript configs), `ee079f8` (husky + lint-staged), `2502ea2` (CI format/lint checks), `6e1d555` (CI scoped to changed files), `ac50c6e` (batch changed-file checks for Windows argv limit), `42f0c8b`+`8e9a0c7` (check-changed from @backstage/scripts) + +## Context + +The repo started as npm-style standalone codemod packages with no shared formatting or CI gates. Per-codemod configs drifted, CI ran everything on every PR, and Windows contributors hit argv-length limits and CRLF mismatches. + +## Decision + +- Yarn 4 via Corepack; `yarn.lock` committed (lockfile v9), `.yarn/install-state.gz` untracked. +- oxfmt + oxlint (not Prettier/ESLint), with a single shared TypeScript config; no per-codemod typescript dependency. +- husky pre-commit runs `yarn lint-staged`; pre-push runs `yarn check:changed`; CI runs the same `check-changed` bin from the private `@backstage/scripts` package, so local and remote gates cannot drift. +- Changed-file checks batch paths and skip ignored test fixtures. + +## Consequences + +Fast PRs (only changed packages gate), one formatting dialect, loud failures when `node_modules` is missing in worktrees. Contributors must use Corepack-enabled Yarn, and Windows argv/CRLF pitfalls are handled centrally rather than per-PR. diff --git a/docs/adr/0002-flattened-recipe-layout.md b/docs/adr/0002-flattened-recipe-layout.md new file mode 100644 index 00000000..ebd3bc6e --- /dev/null +++ b/docs/adr/0002-flattened-recipe-layout.md @@ -0,0 +1,17 @@ +# ADR 0002: One flattened migration recipe per Backstage release + +- **Status**: Accepted +- **Date**: 2026-10-27 → 2026-11-03 +- **Evidence**: `de65869` (bundle 1.54 scripts into the recipe), `fdf77d1` (flatten v1.54.0 + adapt tooling), `f585c23`, `138ae39`, `2d983e2`, `7652a9c`, `e53eaab`, `6d0d7e4`, `57363b7`, `930b994` (fold v1.45–v1.55 into flattened recipes), `defbd23` (fold misc MUI codemods into mui4-to-bui recipe), `d21a333` (integrate flattened layout), `8f470fe` (workflow structural validation) + +## Context + +Codemods were originally standalone registry packages, with recipe workflows referencing them as `codemod:` registry steps. That meant many published packages per release, version coupling between recipe and steps, and no guarantee that a workflow step existed in the checkout it ran from. + +## Decision + +Each Backstage release publishes exactly one `migration-recipe` package at `codemods//`. Workflow steps run local scripts (`js_file: scripts/.ts`); `codemod:` registry steps are structurally rejected by the test runner. The misc recipe keeps its nested root at `codemods/misc/mui4-to-bui-migration-recipe/`. Tooling discovers recipe package roots by convention. + +## Consequences + +Single published artifact per release, workflow and scripts always version together, and recipe PRs are self-contained. Adding a cross-release shared codemod now requires either duplication or folding into an existing recipe — accepted cost. diff --git a/docs/adr/0003-ast-first-ai-fixup-fallback.md b/docs/adr/0003-ast-first-ai-fixup-fallback.md new file mode 100644 index 00000000..1eb7bf69 --- /dev/null +++ b/docs/adr/0003-ast-first-ai-fixup-fallback.md @@ -0,0 +1,17 @@ +# ADR 0003: AST-first codemods, AI fixup only as fallback + +- **Status**: Accepted +- **Date**: 2026-04-23 +- **Evidence**: `32517ac` (deterministic duck-typing from AI to AST), `a882bc6` (namespace/dynamic import handling from AI to AST), `4526cae` (template literal scanning from AI to AST), `aae72ff` + `ed1608d` (deterministic patterns from AI fixup into AST codemod), `d3734c0` (semantic analysis suggestions), `b5f7380`, `2d936f2` (further AI→AST moves) + +## Context + +Recipe workflows originally used AI fixup steps for fuzzy transformations (renames scoped to a receiver type, import handling, duck-typed object matching). AI steps are nondeterministic, hard to test, and produced false positives on unrelated receivers and return values — a long series of follow-up fixes (`d12b8fc`, `8b709dc`, `38f173a`). + +## Decision + +Any pattern that can be expressed deterministically moves into the AST codemod (`js-ast-grep` script with semantic analysis: type anchors, `ref.inside()` for conditional/loop detection, receiver-scoped renames). AI fixup steps remain only for genuinely fuzzy edits the AST cannot decide. + +## Consequences + +Deterministic, fixture-testable transforms; false-positive fixes land once in the script instead of per-run. Residual AI steps are the explicitly acknowledged fuzzy surface — new PRs should justify keeping a pattern in AI rather than moving it to AST. diff --git a/docs/adr/0004-convention-based-test-runner.md b/docs/adr/0004-convention-based-test-runner.md new file mode 100644 index 00000000..af9c916b --- /dev/null +++ b/docs/adr/0004-convention-based-test-runner.md @@ -0,0 +1,17 @@ +# ADR 0004: Convention-based test runner in a private scripts package + +- **Status**: Accepted +- **Date**: 2026-10-27 → 2026-11-03 +- **Evidence**: `320956c` (repo-wide convention-based test runner), `42f0c8b` (recipe test runner into a private workspace package), `8e9a0c7` (all repository scripts into a TypeScript scripts package), `e9adfa5` (shell test harnesses → TypeScript node:test), `846d7b0` (remaining .mjs suites → TypeScript), `8f470fe` (workflow structure validation in the shared runner) + +## Context + +Each recipe carried its own test wiring: shell harnesses, bespoke `codemod jssg test` invocations, and per-package test commands that drifted. Repository tooling (gates, generators, release helpers) was scattered shell/`.mjs` scripts. + +## Decision + +`run-recipe-tests` (a bin from the private `@backstage/scripts` workspace package, declared as a devDependency — no relative paths) discovers suites by convention: `scripts/.ts` + `tests///input.` run as JSSG suites with language inferred from the fixture extension; `tests//assert-fixtures.ts` runs whole-app trees through the recipe workflow; `tests/**/*.test.ts` runs under `node --test`; every `tests/**/tsconfig.json` is type-checked; workflow structure is validated (local `js_file`/`CODEMOD_SCRIPT` must exist, registry steps rejected). All repository tooling lives in `packages/scripts` as TypeScript bins with `node:test` regression tests (`yarn test:scripts`). + +## Consequences + +Adding a step never changes a test command, and shell/.mjs drift is gone. The runner itself is now the critical path: changes to discovery rules require updating its regression tests, and helpers need no same-stem fixture suite (tested through entrypoints or focused `node --test` suites). diff --git a/docs/adr/0005-release-owned-readme-and-versions.md b/docs/adr/0005-release-owned-readme-and-versions.md new file mode 100644 index 00000000..0c7e7b4e --- /dev/null +++ b/docs/adr/0005-release-owned-readme-and-versions.md @@ -0,0 +1,17 @@ +# ADR 0005: Release-owned README and version generation + +- **Status**: Accepted +- **Date**: 2026-10-13 → 2026-11-03 +- **Evidence**: `0fa47b2` (README sync to manual review PR), `5e9246b` (regenerate README on the Version Packages PR), `664f55a` (remove the redundant README-sync workflow), `8e52cb2` (regenerate the README inside the version-packages script), `c11b739` (pin the version-packages README stage in the wiring test) + +## Context + +The root README (codemod index) is generated, but syncing it drifted: a separate README-sync workflow caused churn, codemod PRs regenerated it inconsistently, and hand-edited `version` fields in `package.json`/`codemod.yaml` fought the Changesets bot. + +## Decision + +Changesets owns version bumps. The release workflow's `version-packages` script runs `changeset version && sync-codemod-versions && generate-readme-codemods` as one version commit on the **Version Packages** PR, so changeset consumption, version bumps, `codemod.yaml` sync, and the README always land together. There is no separate README-sync workflow. Codemod PRs leave the README unchanged; drift is regenerated on the next release PR or via `yarn readme` through a normal PR. The stage is pinned by a wiring test. + +## Consequences + +One place generates versions and README; no double-bookkeeping. The cost is that the README can lag `main` between releases (accepted), and manual version edits are always wrong (overwritten on the next Version Packages PR). diff --git a/docs/agents/domain.md b/docs/agents/domain.md new file mode 100644 index 00000000..739d165d --- /dev/null +++ b/docs/agents/domain.md @@ -0,0 +1,51 @@ +# Domain Docs + +How the engineering skills should consume this repo's domain documentation when exploring the codebase. + +## Before exploring, read these + +- **`GLOSSARY.md`** at the repo root, or +- **`GLOSSARY-MAP.md`** at the repo root if it exists: it points at one `GLOSSARY.md` per context. Read each one relevant to the topic. +- **`docs/adr/`**: read ADRs that touch the area you're about to work in. In multi-context repos, also check `src//docs/adr/` for context-scoped decisions. + +If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved. + +## File structure + +Single-context repo (most repos): + +``` +/ +├── GLOSSARY.md +├── docs/adr/ +│ ├── 0001-event-sourced-orders.md +│ └── 0002-postgres-for-write-model.md +└── src/ +``` + +Multi-context repo (presence of `GLOSSARY-MAP.md` at the root): + +``` +/ +├── GLOSSARY-MAP.md +├── docs/adr/ ← system-wide decisions +└── src/ + ├── ordering/ + │ ├── GLOSSARY.md + │ └── docs/adr/ ← context-specific decisions + └── billing/ + ├── GLOSSARY.md + └── docs/adr/ +``` + +## Use the glossary's vocabulary + +When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `GLOSSARY.md`. Don't drift to synonyms the glossary explicitly avoids. + +If the concept you need isn't in the glossary yet, that's a signal: either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`). + +## Flag ADR conflicts + +If your output contradicts an existing ADR, surface it explicitly rather than silently overriding: + +> _Contradicts ADR-0007 (event-sourced orders), but worth reopening because…_ diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md new file mode 100644 index 00000000..c8246d3d --- /dev/null +++ b/docs/agents/issue-tracker.md @@ -0,0 +1,39 @@ +# Issue tracker: GitHub + +Issues and specs for this repo live as GitHub issues on `backstage/codemods`. Use the `gh` CLI for all operations. + +## Conventions + +- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies. +- **Read an issue**: `gh issue view --json number,title,body,labels,comments`. +- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters. +- **Make an issue a sub-issue of a parent**: `gh issue create --parent ...`, or `gh issue edit --add-sub-issue ` afterwards (`gh` 2.94+). Older `gh`: `gh api --method POST repos/backstage/codemods/issues//sub_issues -F sub_issue_id=` (database id, as in **Blocking** below). Without sub-issues, put `Part of #` at the top of the child body. +- **Blocking**: GitHub's **native issue dependencies**, the canonical, UI-visible representation. Add an edge with `gh issue create --blocked-by , ...` or `gh issue edit --add-blocked-by ` (`gh` 2.94+). Older `gh`: `gh api --method POST repos/backstage/codemods/issues//dependencies/blocked_by -F issue_id=`, where `` is the blocker's numeric **database id** (`gh api repos/backstage/codemods/issues/ --jq .id`, _not_ the `#number` or `node_id`). Where dependencies aren't available, fall back to a `Blocked by: #, #` line at the top of the child body. A ticket is unblocked when every blocker is closed. +- **Count open blockers**: `gh api repos/backstage/codemods/issues/ --jq .issue_dependencies_summary.blocked_by` (open blockers only; 0 means startable). `gh issue view --json blockedBy` also lists closed blockers, so filter it: `--jq '[.blockedBy.nodes[] | select(.state == "OPEN")] | length'`. +- **Comment on an issue**: `gh issue comment --body "..."` +- **Apply / remove labels**: `gh issue edit --add-label "..."` / `--remove-label "..."` +- **Close**: post the explanation with `gh issue comment --body "..."`, then `gh issue close `. On an already-closed issue, `gh issue close --comment` drops the comment and still exits 0. + +Infer the repo from `git remote -v`; `gh` does this automatically when run inside a clone. + +Before the first `gh issue create` of a session, check the target with `gh repo view --json nameWithOwner` — in a fork, `gh` can default to the upstream parent. File issues only where the user intends them to live. + +## Pull requests as a triage surface + +**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_ + +When set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents: + +- **Read a PR**: `gh pr view `, then `gh pr view --comments` (off a TTY, `--comments` prints only the comments, not the body), and `gh pr diff ` for the diff. +- **List external PRs for triage**: `gh api --paginate 'repos/backstage/codemods/pulls?state=open' --jq '.[] | select(.author_association | IN("OWNER","MEMBER","COLLABORATOR") | not) | {number, title, author: .user.login, author_association, labels: [.labels[].name]}'`. +- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`. + +GitHub shares one number space across issues and PRs, so a bare `#42` may be either: resolve with `gh pr view 42` and fall back to `gh issue view 42`. + +## When a skill says "publish to the issue tracker" + +Create a GitHub issue. + +## When a skill says "fetch the relevant ticket" + +Read it as in **Read an issue** above. diff --git a/docs/agents/triage-labels.md b/docs/agents/triage-labels.md new file mode 100644 index 00000000..ad2d1cab --- /dev/null +++ b/docs/agents/triage-labels.md @@ -0,0 +1,13 @@ +# Triage Labels + +The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker. + +| Label in mattpocock/skills | Label in our tracker | Meaning | +| -------------------------- | -------------------- | ---------------------------------------- | +| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue | +| `needs-info` | `needs-info` | Waiting on reporter for more information | +| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent | +| `ready-for-human` | `ready-for-human` | Requires human implementation | +| `wontfix` | `wontfix` | Will not be actioned | + +When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table. From 365545023e7a845b6e26227d69c54ae96f9933d5 Mon Sep 17 00:00:00 2001 From: Paul Schultz Date: Tue, 3 Nov 2026 10:53:55 -0600 Subject: [PATCH 2/2] docs: fix review findings in ADRs and REVIEW.md - ADR-0001: recipe-local tsconfigs and newer recipes' own typescript devDependency, instead of the categorical shared-config claim - ADR-0003: attribute the d12b8fc/8b709dc/38f173a fixes to tightening AST receiver/type scoping, not to AI-step false positives - REVIEW.md: check:changed runs CI's changed-file gate; CI additionally runs yarn test:scripts and a Changeset Check job --- REVIEW.md | 2 +- docs/adr/0001-yarn4-oxfmt-toolchain.md | 2 +- docs/adr/0003-ast-first-ai-fixup-fallback.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/REVIEW.md b/REVIEW.md index f39276da..591a5424 100644 --- a/REVIEW.md +++ b/REVIEW.md @@ -27,4 +27,4 @@ What failure looks like in this repo, for AI reviewers. A PR that passes CI can ## What good looks like -`yarn format`, `yarn lint`, `yarn test` pass locally — and `yarn check:changed` reproduces exactly what CI runs, so local and remote gates cannot drift. The pre-commit (`yarn lint-staged`) and pre-push (`yarn check:changed`) hooks fail loudly rather than silently skipping. +`yarn format`, `yarn lint`, `yarn test` pass locally — and `yarn check:changed` runs the same changed-file gate CI runs (format, lint, package-name, affected recipe tests), so that gate cannot drift. CI additionally runs `yarn test:scripts` (the `packages/scripts` regression tests) and a Changeset Check job — run `yarn test:scripts` locally before pushing tooling changes. The pre-commit (`yarn lint-staged`) and pre-push (`yarn check:changed`) hooks fail loudly rather than silently skipping. diff --git a/docs/adr/0001-yarn4-oxfmt-toolchain.md b/docs/adr/0001-yarn4-oxfmt-toolchain.md index d34cbcc3..40a3826e 100644 --- a/docs/adr/0001-yarn4-oxfmt-toolchain.md +++ b/docs/adr/0001-yarn4-oxfmt-toolchain.md @@ -11,7 +11,7 @@ The repo started as npm-style standalone codemod packages with no shared formatt ## Decision - Yarn 4 via Corepack; `yarn.lock` committed (lockfile v9), `.yarn/install-state.gz` untracked. -- oxfmt + oxlint (not Prettier/ESLint), with a single shared TypeScript config; no per-codemod typescript dependency. +- oxfmt + oxlint (not Prettier/ESLint) as root tooling; recipes keep recipe-local `tsconfig.json` files, and the newer recipes (`v1.54.0+`) declare their own `typescript` devDependency. - husky pre-commit runs `yarn lint-staged`; pre-push runs `yarn check:changed`; CI runs the same `check-changed` bin from the private `@backstage/scripts` package, so local and remote gates cannot drift. - Changed-file checks batch paths and skip ignored test fixtures. diff --git a/docs/adr/0003-ast-first-ai-fixup-fallback.md b/docs/adr/0003-ast-first-ai-fixup-fallback.md index 1eb7bf69..b6a07cbd 100644 --- a/docs/adr/0003-ast-first-ai-fixup-fallback.md +++ b/docs/adr/0003-ast-first-ai-fixup-fallback.md @@ -6,7 +6,7 @@ ## Context -Recipe workflows originally used AI fixup steps for fuzzy transformations (renames scoped to a receiver type, import handling, duck-typed object matching). AI steps are nondeterministic, hard to test, and produced false positives on unrelated receivers and return values — a long series of follow-up fixes (`d12b8fc`, `8b709dc`, `38f173a`). +Recipe workflows originally used AI fixup steps for fuzzy transformations (renames scoped to a receiver type, import handling, duck-typed object matching). AI steps are nondeterministic and hard to test. Moving the patterns into deterministic AST transforms then required a series of follow-up fixes to tighten receiver and type scoping (`d12b8fc` guard on call arguments, `8b709dc` narrowing to return types, `38f173a` scoping renames to `DialogApi` receivers) — the cost of getting deterministic detection right. ## Decision