How do I create a PR?

Table of Contents

The body content should be assembled via How do I generate a PR summary? before running the gh command here.

1. Question

How do I open a pull request from my current feature branch, with a correctly-formatted title and a structured body?

2. Answer

  1. Build and run tests locally first — mandatory, never skip. CI does not run a full C++ build/test job on PRs (the old "canary" job was removed — it took too long and slowed down development), so this local step is the only thing that catches a broken build before review, and the PR description (step 3) is the only record that it happened: ./compass.sh build --preset <preset> (not raw cmake --build, so it takes the host-wide build lock — see How do I build the system?) then ctest --preset <preset>, both clean, before proceeding.
  2. Close task/story bookkeeping now, if not already done — task DONE, * Result written, story/sprint rows synced (see compass-agile-close-task). This happens before raising the PR, so the bookkeeping commit is part of the very first push, not a follow-up after review.
  3. Create the PR with compass pr create. It validates the title convention, refuses the raise when a required Testing flag carries no text, and assembles one fixed body template: ## Summary, ## Changes, the ## Traceability table derived from the branch's task and story docs (with an Environment row alongside Story and Task), ## Testing, then the footer. The step-1 verification result goes in the Testing section, emitted as Plan., Evidence. and Limitations. paragraphs from --testing-plan, --testing-evidence and --testing-limitations, so it is visible in the description without asking. It then pushes the branch, opens the PR, records it on the task (#+pr: and the * PRs table), commits and pushes that record, and stamps the session journal:

    ./compass.sh pr create --title "[component] One-line description" \
      --summary "What changes, why." \
      --change "First change" --change "Second change" \
      --testing-plan "What will be tested, and how." \
      --testing-evidence "Local build clean (<preset>); ctest <N>/<N> passed" \
      --testing-limitations "What was left untested."
    

    Use --draft for a draft PR, --task <uuid-or-slug> when the branch carries more than one task, and --environment <name> to override the environment shown (default: the task's #+environment: frontmatter field, e.g. prime_origin; falls back to (none) if the task doesn't record one).

  4. Confirm the PR URL it prints. There is nothing else to do — the task-doc record is already committed and pushed.

3. Conventions

  • PR body is Markdown, not org-mode. GitHub renders the body as Markdown; use **bold**, `code`, [text](url) etc. — never [[id:...]] links, #+begin_src blocks, or other org syntax.
  • Body template is fixed. Every compass pr create body has the same four sections — Summary, Changes, Traceability, Testing — then the 🤖 Generated with Claude Code footer. Sections may be expanded (Notes, Decisions, Follow-ups) and the optional Captures section may be inserted before Traceability, but Testing is never omitted: the generator requires --testing-plan, --testing-evidence and --testing-limitations text and refuses the raise when any is missing.
  • Testing section carries three plain paragraphs — Plan., Evidence. and Limitations. — one per required flag, under a ## Testing heading after the Traceability table and before the footer. The Evidence paragraph holds the step-1 verification (change class, checks run, results); Limitations names what was not tested.
  • Title format is [COMPONENT] Description. Multi-component PRs use [a,b,c].
  • Captures section (optional): the captures you filed while working — a bug, limitation, or idea noticed in passing and recorded with compass capture (it lands in the product-backlog inbox, not as a story task). List one Markdown link per line to each capture's published page, so what you deferred is traceable from the PR. The same un-assigned captures also surface in the sprint's * Captures section. Place it just before Traceability. compass pr create does not yet generate this section — add it by hand (or via =–summary=/body editing) until it does.
  • Traceability section follows the Changes section and precedes the Testing section, always. It is a Markdown table with three columns — Artefact, Link, ID — and one row per tracked artefact (Story, Task), plus a final Environment row so it's visible at a glance alongside Story and Task rather than buried in prose. The Link cell contains a markdown hyperlink to the published HTML page; the ID cell contains the full UUID as read from the :ID: property of the .org file. Never abbreviate the UUID to just the first segment.
  • Story and task page URLs follow the pattern: https://orestudio.github.io/OreStudio/<path-without-extension>.html where <path> is the file path relative to the repo root:
    • Story: doc/agile/versions/v0/sprint_<NN>/<STORY_SLUG>/story
    • Task: doc/agile/versions/v0/sprint_<NN>/<STORY_SLUG>/task_<TASK_SLUG>
  • Traceability is forward-only: add it to new PRs; do not back-fill old ones.
  • Environment row is the last row of the Traceability table, always: | Environment | <name> | |. It records which ores_dev_* worktree environment the work was done in (read from the task's #+environment: field), so a reviewer or a later session can tell where to reproduce/continue the work at a glance, without opening the description body. (none) if the task doesn't record one.

4. Script

compass pr create (projects/ores.compass/src/compass_pr.py) wrapping gh pr create. The gh CLI must be authenticated (gh auth login) once per checkout.

5. Tested by

Manual. Reviewers verify the PR shape; compass pr checks reports CI.

6. See also

Emacs 29.3 (Org mode 9.6.15)