Shikanime Org PR Creation
Open PRs against shikanime-labs/* and shikanime-studio/*: push to origin,
open with --head <org>:<branch>, base main, plain-English (or doc:) title,
issue linkage. Repo enforcement (branch protection, CI, hooks) is detected per
repo.
When to Use
- "Open a PR in a shikanime org repo."
- "Ensure issue linkage before creating a PR."
- "Push to origin and land via plain
gh pr(the org removedgh stack)."
Internal policy: push to origin
All PRs open from origin (the cloned org repo). Push the branch to origin
and open with --head <org>:<branch>. The local path may read shikanime-labs
while the gh remote is shikanime-studio (e.g. nix-containers) — trust the gh
remote as canonical.
Prerequisites
ghauthenticated; active identity is a collaborator with push right. Do NOTgh auth switch; push toorigindirectly.- Linked issue exists (see
sks-issue); verify it matches the change (jj file annotate/jj show <commit>if unsure). - Branch pushed to
originbefore opening.
Org PR conventions
- Base —
mainunless the default differs (gh repo view <org>/<repo> --json defaultBranchRef). - Title — commit subject (plain English /
doc:), NO conventional prefix; parity with commit. - Body — restates the commit body as three fixed sections (commit is the
source of truth; restate, do NOT invent new rationale):
## What— one-line summary + bullet scope (what this PR delivers).## Why— why now: the drift/risk/pain this closes (one short paragraph).## References—Related: <full issue URL>(mandatory) plus any commits/specs/changelogs proving the solution.- See
references/example-pr-body.mdfor a filled example. - GitHub PR body is free text — never wrap lines and never insert hard line
breaks at a column width. Write natural paragraphs; a blank line
separates paragraphs, everything else renders as-is. Never run
nix fmt/mdformatover a PR body; those tools enforce an 80-column wrap that does not apply to GitHub bodies. - Encourage a Mermaid diagram (e.g.
flowchart TD) in the body when a visual aids the reader — GitHub renders Mermaid inline in PR bodies. The diagram is optional reinforcement, never a substitute for the## What/## Why/## Referencesstructure. - A bare
@namein prose pings that user/team — wrap any literal@(NestJS@Inject(x), decorators, config keys) in a code span or fenced block; only code disables mention parsing. - Use full URLs — never bare
#XXXX/owner/repo#XXXX(broken):Related: https://github.com/<org>/<repo>/issues/N(same repo) orRelated: https://github.com/owner/repo/issues/N(cross-repo). List each URL on its own line. Repo-enforced shape (e.g.manifestsAGENTSfile:Related:+Signed-off-by) overrides — follow the repo. - Guard — PR template ≠ issue template: the PR body NEVER uses the
issue's
## Problem/## Acceptanceshape. A body that copies the issue template, leaks a bare#N, or invents a field (e.g.Stacks on:) is a defect — reject and rewrite before opening. - Linkage is many-to-many (discussion → issue → comments → PR): a PR
always solves an issue. Default
Related: <issue URL>; otherwise close deliberately after final merge (verify N-of-N, thengh issue close). Same deliberate close (seesks-dev-workflow).
- Head —
--head <org>:<branch>; push tooriginonly. - Parity — PR title MUST equal commit subject; PR body MUST restate the
commit message; no added rationale (see
sks-commit).
Landing via plain gh pr
The org removed the gh stack extension — land with plain gh pr merge (see
sks-land). Squash-merge keeps a linear history and preserves PR↔commit parity
(title = commit subject, body = commit message).
jj rebase -d main # ALWAYS rebase onto trunk before landing
gh pr merge <M> --repo <org>/<repo> --squash --admin \
-b "$(cat <<'EOF'
<body: one coherent change, no jj * bullets / --------- separators;
trailers only: Related: [url], Signed-off-by: [user]>
Co-authored-by: Automata <automata@shikanime.studio>
EOF
)" # --admin bypasses self-approval protection
- Branch protection blocks self-approval on some repos (e.g.
shikanime-labs/skills); a verballgtmsatisfies the gate — land with--squash --admin. - Conflict check before merge:
gh pr view <N> --json mergeable,mergeStateStatus(existing PR) orjj rebase -d mainlocally (conflict markers = author rebases; never push a conflict). - For a lone branch use step 2b (
gh pr create); landing still applies.
Procedure
1. Branch + commit
- Feature branch off
main(e.g.fix/rwx-nfs-v4.0).mainis protected on some repos (e.g.shikanime-studio/actions) — never commit directly tomain. - Commits per
sks-commit(plain English /doc:; repo hook policy wins).
2. Rebase onto main + resolve conflicts (MANDATORY before any push)
jj rebase -d main
- Conflict or
<<<<<<<markers: STOP. Resolve (keepmain's additions AND the fix), thenjj squash/jj resolve. Never push conflict markers. jj rebaserewrites commits and drops signatures (jj auto-sign does not fire) — re-sign withjj sign -r @and re-point the bookmark (jj bookmark set <branch> -r @) before pushing (seesks-dev-workflow).
2b. Duplicate / stack check (MANDATORY before gh pr create)
Before opening ANY new PR, enumerate what already exists:
gh pr list --repo "$ORG/<repo>" --state open --json number,title,headRefName \
--jq '.[] | "\(.number)\t\(.title)\t\(.headRefName)"'
- Duplicate — an open PR already delivers this change (same files/intent): do NOT open another. Push your revision onto that PR's branch or comment instead.
- Stack required — an open PR touches the same area and your change depends
on it (or conflicts without it): base your branch ON that PR's head branch,
not
main. Open yours--base <their-branch>(re-base tomainafter theirs lands). Record both PR URLs inRelated:. - Neither — proceed with
--base main.
2c. Push to origin + open PR
ORG=<org>
jj git remote add origin "git@github.com:$ORG/<repo>.git" 2>/dev/null || true
jj bookmark track <branch> --remote=origin
jj git push --remote origin
gh pr create --repo "$ORG/<repo>" --base main --head "$ORG:<branch>" \
--title "TITLE" --body "$(cat <<'EOF'
## What
## Why
## References
<linked issues/PRs, commits, changelogs, specs proving the solution>
Related: https://github.com/<org>/<repo>/issues/N
EOF
)"
Use --draft when checks aren't green yet.
2d. Verify mergeable after submit
gh pr view <N> --repo "<org>/<repo>" --json mergeable,mergeStateStatus
# expect mergeable="MERGEABLE"; "CONFLICTING" = rebase didn't take,
# "BEHIND" = main advanced (rebase again)
GitHub's mergeable is computed lazily — a fresh jj rebase -d main + re-push
forces recompute. Don't declare done on stale CONFLICTING.
2e. On revision (PR already open): reconcile review threads
New commits void prior review. Before done: (1) load sks-pr-resolve, drive
every thread to resolved — address pertinent in diff, discard non-pertinent with
a one-line comment, never silently; (2) re-run sks-pr-review if logic changed;
(3) verify the issue's DoD ledger is still N-of-N against the new head.
3. Apply triage metadata
Delegate to sks-pr-triage (#N): sets empty determinable fields (labels,
assignee, milestone, project, reviewers). Rules live in sks-pr-triage; don't
re-derive here.
Post-steps
- Protected
main(e.g.shikanime-studio/actions): a separate approving review may be mandatory; don't self-merge if blocked. - Merging: on
nix-containers"merge the PRs", usegh pr merge --squash --admin -b "<clean body>"(admin required; no-mon currentgh— pass body via-b, seesks-land). Other repos: merge per allowed strategy once green + reviewed. - Direct landing: user authorizing "push to main" / "land it" overrides the PR path — push directly, don't open a PR.
- Docs follow-up: if this PR changes user-facing behavior or adds a feature,
plan a
sks-docupdate underdocs/after merge.
Verification
gh pr view <N> --repo <org>/<repo> --json title,baseRefName,body
Confirm base is main (or repo default), title is plain-English/doc:, body
links the correct issue, and mergeable="MERGEABLE" (step 2d).
See also
sks-commit(parity rule) ·sks-issue-refine(converged issue) ·sks-async(stacked PRs) ·sks-pr-triage(metadata).