Skip to content

PR Format#

Pull requests in the MSX ecosystem double as release notes. The description is written for end users of the solution, not for reviewers or developers. Implementation details go in a clearly separated technical section at the bottom.

Title#

<Icon> [<Type>]: <User-facing outcome>
  • The Icon matches the change type.
  • The Type in brackets is one of: Major, Feature (Minor), Patch, Fix, Docs, Maintenance.
  • The outcome describes what changed from the end user's perspective. Never internal function names, class names, refactoring verbs.

Good titles#

  • ๐ŸŒŸ [Major]: Legacy export command removed
  • ๐Ÿš€ [Feature]: Custom templates now supported
  • ๐Ÿฉน [Patch]: Default timeout value corrected
  • ๐Ÿชฒ [Fix]: Parameter validation no longer fails on null input
  • ๐Ÿ“– [Docs]: Installation guide updated with prerequisites
  • โš™๏ธ [Maintenance]: Release workflow and dependencies updated

Bad titles#

  • Add support for custom templates โ€” describes the action, not the outcome.
  • Refactor parameter validation logic โ€” implementation language.
  • Update stuff โ€” meaningless.

Change types#

Type Icon Label Description
Major ๐ŸŒŸ Major Breaking changes that affect compatibility
Feature ๐Ÿš€ Minor New features or enhancements
Patch ๐Ÿฉน Patch Small fixes or improvements
Fix ๐Ÿชฒ Patch Bugfixes (Patch-level release impact)
Docs ๐Ÿ“– NoRelease Documentation changes only
Maintenance โš™๏ธ NoRelease CI/CD, build configs, AI/agent files, internal upkeep

Detecting the change type#

The change type is decided in this order:

  1. Explicit user input โ€” if the contributor / Shipper specified a type, use it.
  2. Pre-1.0.0 rule โ€” projects with no version tags or latest tag below v1.0.0 follow SemVer ยง4. Major is never auto-detected for pre-1.0.0 projects. Breaking changes there are classified as Minor (0.x.0).
  3. Artifact-based inference from the branch diff:

    Artifact type How to recognize Important files (affect artifact) Non-important (framework / tooling)
    Library / Module src/ with the library's source and a package manifest src/**, package manifest .github/**, *.md, tests/**, scripts/**, agents/**
    GitHub Action action.yml at repo root action.yml, src/** .github/**, *.md, tests/**, agents/**
    Reusable Workflow .github/workflows/ with callable workflows .github/workflows/** *.md, tests/**, agents/**
    Infrastructure module *.tf with input variables and outputs *.tf, *.tf.json .github/**, *.md, tests/**, examples/**
  4. Classification rules (apply in order):

    1. Docs โ€” all changes are documentation only.
    2. Maintenance โ€” all changes are non-important for the artifact (no shipped change).
    3. Patch โ€” important-file changes are small fixes or minor improvements.
    4. Minor โ€” important-file changes add features without breaking.
    5. Major โ€” important-file changes break backward compatibility (pre-1.0.0 โ†’ downgrade to Minor).

If the branch contains both important and non-important changes, classify based on the important changes only.

Description structure#

Ordered, top to bottom.

1. Leading paragraph โ€” Summary#

A concise paragraph describing what changes for the user. Present tense, active voice. Never open with implementation language ("Refactored", "Updated class", "Added null checks").

2. User-facing changes โ€” sections with headers#

Organize by what the user experiences, not by what was changed internally.

  • ## Breaking Changes โ€” what stopped working or changed incompatibly (Major only).
  • ## New: <capability> โ€” new things the user can do.
  • ## Changed: <behavior> โ€” existing behavior that now works differently.
  • ## Fixed: <problem> โ€” problems now resolved.

Under each header:

  • What the user can now do, or what changed for them.
  • What they need to do differently โ€” migration steps, new parameters, changed defaults.
  • Examples or code snippets showing new usage.

Do not mention internal function names, class names, private APIs, or refactoring decisions here.

3. Required ending blocks#

At the very end of every PR description, use this exact structure:

---
<details>
<summary>Technical details</summary>

...

</details>

<details>
<summary>Relevant issues (or links)</summary>

- Fixes Owner/Repo#123
- Owner/OtherRepo#124

</details>

The Technical details block is for reviewers and maintainers. Include internal implementation notes such as:

  • Which internal functions, classes, or files were changed.
  • Implementation approach and design decisions.
  • Backward compatibility notes for developers.
  • Implementation plan progress โ€” cross-reference the closing Task or Bug's plan. Which plan steps does this PR complete? Which were moved to follow-up delivery issues?
  • Standards and framework alignment โ€” the result of the alignment pass, as one row per changed surface. The stage procedure owns when and how the pass is run; this block only carries its evidence.
  • Issue convergence sweep โ€” the scope used for the session-end sweep and which additional open issues (if any) the finished diff fully satisfied.
Changed surface Standards checked Framework docs checked Result
src/** (PowerShell) Naming, Functions Module source layout Aligned
.github/workflows/** GitHub Actions Reusable workflow contract Exception โ€” Owner/Repo#123

A result is Aligned, Fixed in this PR, or Exception with a link to the follow-up issue that carries it. A surface with no framework or domain documentation of its own is recorded as None (no framework-specific docs).

The Relevant issues (or links) block is required and uses fully qualified references (Owner/Repo#N) so links work across repositories.

Use one bullet per linked issue. One bullet uses a closing keyword (Fixes, Closes, or Resolves) for the scoped Task or Bug delivered by the pull request. Additional bullets may also use closing keywords only for issues the issue convergence sweep confirms are fully satisfied by the same finished diff. A parent PBI or Epic may appear as context without a closing keyword; never close an aggregate through a delivery pull request. Partially convergent or supporting issues are linked as non-closing context.

If there is not one scoped closing Task or Bug: stop. Route back to Define to create or correctly route the delivery leaf. If additional closing keywords are used, include sweep evidence in Technical details that shows those issues are fully satisfied. The Issue Hierarchy and Issue Lifecycle own type and closure semantics.

Formatting#

  • Paragraphs are written as a single unbroken line. GitHub renders mid-paragraph newlines as spaces.
  • The PR description is the release note. Write it for users, not reviewers.
  • The PR title and description align with the closing Task or Bug's user-facing framing and recorded technical decisions.

Example#

Repository objects now include custom properties directly โ€” no separate API call needed. Queries that encounter missing or inaccessible resources now return partial results with warnings instead of failing entirely.

## New: Custom properties on repository objects

The `repo get` command now returns custom properties inline on the repository object. Previously, retrieving custom properties required a separate `repo properties` call.

```text
repo get --owner MyOrg --name MyRepo --format table
```

The `repo properties` command remains available if only the properties are needed.

## Fixed: Queries no longer fail when a resource doesn't exist

Commands that query a specific repository, enterprise, or release by name now return nothing instead of throwing when the resource doesn't exist. This makes them safe to use in conditional logic without error handling.

---
<details>
<summary>Technical details</summary>

- The repository model's custom-properties field is now a typed collection rather than an untyped object.
- The GraphQL query layer splits error handling into partial-success (data + errors โ†’ warnings) and full-failure (errors only โ†’ terminating error) branches.
- Null guards added to the repository lookup helpers.
- Implementation plan progress: tasks 1โ€“3 in #218 completed; task 4 (integration tests) remains.

</details>

<details>
<summary>Relevant issues (or links)</summary>

- Fixes Owner/Repo#218
- Owner/Repo#219

</details>

Drafts and readiness#

  • The Shipper always creates the PR as draft so CI attaches immediately.
  • A pull request is marked ready only when it meets every item in the Definition of Ready for Review โ€” nothing in that gate is left open. That page is the single checklist; this section does not restate it.
  • Marking ready is a gate, not a person: anyone who can verify that gate โ€” a contributor, or an agent acting on their behalf โ€” may mark it ready. The gate, not the actor, is what makes it ready.
  • Once ready, enable auto-merge (squash) so the change lands when review approves and the required checks stay green. See Branching and Merging.

Branches and commits#

  • Branch naming: <type>/<issue-number>-<short-slug>, e.g. fix/123-pagination-truncation.
  • Commit messages: plain, direct, descriptive. No conventional-commit prefixes (fix:, feat:, docs:). See Commit Conventions.
  • Self-review the staged diff before each commit. Unintended files (debug output, editor temp, credentials) get caught before they reach the remote.

Labels and assignment#

  • Apply the change-type label.
  • Apply phase labels if the repo uses them (Planning, Implementation, etc.).
  • Assign the current user.
  • Request reviewers per CODEOWNERS; if none, fall back to repo defaults or skip.