azure-cli-extensions / migrate
AGENTS.md455 starsChanged 18 months agoMITView on GitHub
This file is a standing instruction for any agent doing coding work anywhere under src/migrate/. Treat every change as if you are the principal engineer who must approve the pull request. Do not merely make code work — make it the code a principal engineer would sign off on. Before finishing ANY migrate task, rigorously self-review against these criteria and reject your own work if it fails: 1. Simplicity — Is this the simplest solution that fully solves the problem?…
- Installs packages
We split this AGENTS.md into the rules it gives an agent
7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 10
Before finishing ANY migrate task, rigorously self-review against these criteria and reject your own work if it fails:
- Distinctive: line 31
9. If below 9, keep simplifying.
- Distinctive: line 36
Every non-trivial migrate change MUST end with a 10-point engineering review covering:
- Very specific: line 58
Every change under azext_migrate/runbook/ MUST run the coverage script and keep total coverage ≥ 95%.
- Distinctive: line 80
Every code change updates its tests in lockstep: If you change a contract (request body, command signature, transformer columns, …
- Distinctive: line 84
Green-before-done: Run the unit suite (see Verification gate) and confirm it passes before declaring any change complete.
- Very specific: line 89
If collection counts look inflated or failures vanish inexplicably, delete src/migrate/build/ (a regenerable artifact) and clear …
≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Principal Engineer Review Mode — migrate extension
This file is a standing instruction for any agent doing coding work anywhere under
src/migrate/. Treat every change as if you are the principal engineer who must approve
the pull request. Do not merely make code work — make it the code a principal engineer would
sign off on.
Non-negotiable review discipline
Before finishing ANY migrate task, rigorously self-review against these criteria and reject your own work if it fails:
- Simplicity — Is this the simplest solution that fully solves the problem? Remove any complexity that does not earn its place.
- Reuse first — Prefer existing helpers, patterns, and abstractions over new ones. Search
before you write. (
shared/,runbook/, existingArmClient/filespatterns.) - Architecture fit — The change must match the established structure (REST via
ArmClient,shared/files.pyfor archive/IO,runbook/cmds/*for command logic,transformers.pyfor table shaping). No parallel or competing mechanisms. - No speculative code — Do not add constants, parameters, branches, or error handling for cases that cannot occur or are unproven. Validate only at real system boundaries.
- No duplicate logic — Collapse repeated iterate/parse/classify/format loops into a single source of truth. Duplication is a defect.
- Root-cause fixes only — Fix the underlying cause, never paper over a symptom. State the root cause explicitly in your summary.
- Net code growth — Prefer changes that remove more than they add. Justify every new abstraction with a concrete, present-day need and a net-complexity benefit.
- Security by design — Prefer designing hazards out (e.g. flatten to basename to eliminate zip-slip) over runtime guards. Keep the OWASP Top 10 in mind for every I/O boundary.
- Maintenance score — Rate the resulting code 1–10 for maintainability. Do not ship below 9. If below 9, keep simplifying.
- PR approval test — Ask: "Would I approve this PR as principal engineer?" If not, revise.
Mandatory concluding deliverable
Every non-trivial migrate change MUST end with a 10-point engineering review covering:
- Selected design and why it won.
- Alternatives considered and why they were rejected.
- What existing code was reused.
- What was refactored/consolidated.
- Duplicate logic removed.
- New abstractions introduced and their justification.
- Net lines added vs. removed.
- Remaining technical debt (with explicit
TODO(confirm)where behavior is unverified). - Maintenance score (1–10) with rationale.
- Why this is the simplest correct solution.
Verification gate (always run before declaring done)
python -m pytest migrate/azext_migrate/tests/latest/runbook/test_runbook_unit.py -qpython -m azdev style migratepython -m azdev linter migrate(the trailingERROR: invalid git repo: Noneis harmless)python src/migrate/scripts/runbook_coverage.py— runbook coverage; fails under 95% by default.
Runbook code coverage — calculate and display on every code change
Every change under azext_migrate/runbook/ MUST run the coverage script and keep total
coverage ≥ 95%; report the TOTAL line in the PR summary so reviewers see the delta.
- Run:
python src/migrate/scripts/runbook_coverage.py - It runs the runbook unit + scenario suites under
coverage(config:src/migrate/.coveragerc), scoped toazext_migrate/runbook, prints a per-file table +TOTAL, and exits non-zero below 95% (--fail-under 95is the default; pass--fail-under 0to only report). - Paste the
TOTALline (and any files whose coverage dropped) into the PR summary. - Prerequisite:
pip install coverage(not part of the default env). - Excluded from measurement (see
.coveragerc/# pragma: no cover), do NOT try to test these:params.py— declarative CLI arg registration, exercised by the command-table/linter, not units.execution.py_watch/_watch_visualize— interactivewhile True+time.sleeppolling loops.
- New logic MUST ship with tests in the same change (see "Tests move with the code").
- The
.coveragedata file is a git-ignored artifact — never commit it.
Tests move with the code — never leave a reconciliation gap
Code and its tests are ONE change. A task is not done until the tests that cover the changed behavior are updated in the SAME change and the suite is green.
- Every code change updates its tests in lockstep. If you change a contract (request body, command signature, transformer columns, file/archive handling, action verb, call kwargs), update the covering unit/scenario tests in the same edit. Never defer test updates to "later" or to a separate reconciliation pass.
- Green-before-done. Run the unit suite (see Verification gate) and confirm it passes before declaring any change complete. A change that leaves failing tests is an unfinished change.
- Tests must load the source under
src/migrate/azext_migrate/, not build artifacts. Run pytest withcwd = src/migrate. A stalebuild/lib/azext_migratecopy can shadow/merge with the source package and mask source/test drift (a suite may appear to pass against the stale copy). If collection counts look inflated or failures vanish inexplicably, deletesrc/migrate/build/(a regenerable artifact) and clear__pycache__, then re-run against source. - Root cause of drift: code advanced while its tests were not updated in the same change. Do not recreate that state. When source and tests disagree, the source is authoritative only because it was reviewed — still confirm the current behavior is intended before aligning the test to it.
Domain facts to preserve
- Terminology: display "step group" = wire "workstream". User-facing surfaces
(CLI command group
definition step-group, params--step-group-id/--source-step-group-ids/--new-step-group-name, table columnStep Group Id, HTML labelsStep group: …) say "step group". The API bodies,spec.json/executionStatus.jsonkeys (workstreams,workstreamId),-o jsonoutput, and all internal code/file names (definition_workstream.py,class Workstream,workstream_idparams) stayworkstream. Rename only at the display + CLI-arg edges. - Downloaded runbook archive members (service renamed 2026-08-25):
spec.json→ the definition ({"spec": {...}}).inputs.json→ the parameters ({"inputs": {...}}).definition downloadwrites this alongside the definition (per-stepconfigurationStatusis derived from it), but table/CLI output (show,visualizegrid) still renders the definition only.system-derived-inputs.json→ same shape as inputs; never downloaded/rendered by any CLI. It is distinguishable from the user inputs ONLY by filename, so it is excluded by name (shared/files.py::_DERIVED_INPUTS_NAMES).executionStatus.json→ the per-execution status document (File-mode SAS download).
- Archive members are classified by content, not filename suffix (member naming varies across
services, e.g.
rb-<name>-spec.jsonvsspec.json). Seeshared/files.py::_classify_archiveas the single source of truth. Only the derived-inputs exclusion and the File-mode download/upload paths are name-sensitive (runbook/constants.py): parameter upload now targetsparameters.jsonONLY (the service rejectsinputs.json, for both runbook and execution inputs);executionStatus.jsonis the File-mode status download. - UpdateStep/AddStep
dependsOnwrite contract: each entry is a polymorphicRunbookStepDependency; the discriminator"waitFor"is one ofStep/Entity/MappedEntities.Entity/MappedEntitiesare invalid for Manual steps (only entity-bearing steps, e.g. Approval);MappedEntitiescarries anentityPairs[{"dependentEntity", "waitsFor"}]list,Entitycarries none,Stepcarries none. The CLI authors all three viastep add/step updateflags--depends-on-whole-step(Step),--depends-on-per-entity(Entity),--depends-on-mapped-entities(<stepId>=<dep>:<up>,...→ MappedEntities). Seemodels.py::build_step_dependencies/_mapped_dep. Replace vs preserve: when any flag is given the combined list fully replacesdependsOn(unspecified modes dropped); when none are givenbuild_step_dependenciesreturnsNoneandbuild_update_step_bodysendsdependsOn: null, which the service treats as preserve existing (AddStep sends[]instead — a new step has nothing to preserve). No read-modify-write. Manual-step rejection is enforced client-side only onadd(which knows the step type);updatedefers to the service. Entity ids in pairs are bare GUIDs.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repositoryOne other file it gives its agents.
- .github/copilot-instructions.mdCopilot instructions
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

