Skip to content

/plate

When to invoke: Turn finished local work into a commit, an ordinary pull request, or a pull request stack. Use this skill to commit changes or to publish a branch. Use it to open or update a pull request. Use it to create, sync, restack, or submit a pull request stack. You can also run /plate. This skill owns all staging, commits, pushes, pull request creation, and stack changes. GitHub inspection, reviews, comments, CI, issues, releases, and repository administration are outside this skill. Use the gh CLI directly for that work.


Plate completes local work before review. It finishes required artifacts, validates, commits safely, and selects the correct publication path.

Run python3 skills/plate/scripts/plate.pyz wheypoint-resolve --ref <slug>. authoritative uses the record; its working_context is the first batched tilth_read. not-found proceeds cold; legacy shows its source and slug, then proceeds. gated, ambiguous, and error stop and show the payload. Show advisory stale-commit and grounded-path-missing findings.

Plate resolves the slug and reads the result, but it does not commit a wheypoint revision or publish a wheypoint revision.

Check ownership before you select a mode. /plate owns staging, commits, pushes, ordinary pull request changes, and pull request stack changes.

  • /plate never performs code-quality review. It never computes a review surface for its own sake. Review is /age.
  • GitHub inspection, reviews, comments, CI, merges, issues, workflows, releases, search, and administration are outside /plate. Use the gh CLI directly when no local publication transaction is necessary. Use /affinage to act on pull request feedback or CI failures.
  • A request that only reads or assesses GitHub or diff state leaves /plate before any mode is selected. Thus, routing it here is a plate-owned failure.
  • Destructive deletion, history rewrites, unsafe force-pushes, and protected-branch changes require explicit user authorization.

Classify every invocation into exactly one mode. Load one reference at a time. Do not read the others.

Mode Trigger Load
Commit-only Save local work without publishing it references/durable-writes.md
Topology preflight Persist the new-PR layout before another workflow creates commits or branches references/topology.md
New PR No PR exists for the branch and publication is requested references/topology.md
Existing PR Update a PR while preserving its current topology references/ordinary-pr.md
Stack maintenance Create, sync, restack, submit, recover, or explicitly ship a stack references/stacks.md

Inspect a stack only as a step of a requested stack change. Route a stack inspection request without a requested change out of /plate to the gh CLI.

New-PR work loads its references in this sequence. Load each reference alone. Close it before you load the next one.

  1. Load references/topology.md. Resolve the topology. Plate decides it and does not ask the user.
  2. Load references/ordinary-pr.md for the single or orthogonal_flat shape. Load references/stacks.md for a stacked shape.
  3. Load exactly one provider reference from references/stacks.md for a stacked shape. The provider references are gt.md, git-town.md, and gh-stack.md. When no provider is usable, references/stacks.md routes to setup.md.

When an existing pull request uses a stack, load references/stacks.md. Do not use a bare single-branch push.

Accept --hard to run /hard-cheese immediately before you first share the work for review. Give that gate one JSON context. Include the final artifact inventory, the completion rows, the tracked artifact diff digest, and the quality gate result. Do not give it an earlier implementation snapshot.

Read the gate status. Then apply this matrix:

Gate status Response
PASS Continue to publication
LOGGED Continue to publication. Record the logged findings in the pull request body
ERROR Ask the user before you publish. Report the gate error
FAILED Halt at quality gate. Do not publish. Fix the work

Ask the ERROR question through the shared question transport. See ../cheese/references/ask-user-question.md.

  • Run python3 skills/plate/scripts/plate.pyz stack-tools before you select a stack provider. The command detects Graphite, Git Town, and gh stack. It does not change repository state.
  • Use Git and GitHub for repository, remote, and PR state. Use the selected provider CLI for stack state.
  • Use the repository code-intelligence backend to edit tracked artifacts. Use the same backend to read them. Select the backend with code-intelligence-routing.md. Follow this sequence from references/durable-writes.md: fresh tagged read, one stale-safe write, diff read-back. Use named paths. Do not use shell redirects.
  • Send durable wiki knowledge through /wiki-ingest. Do not edit the Hallouminate tree directly.
  • Keep temporary completion and PR-body files under .cheese/. Do not stage them.
  • Slash commands are host renderings, not the control model. Name the capability before you show a host example. See ../cheese/references/harness-portability.md.

Commit-only work and ordinary PR work use this transaction. Stacked work uses the per-layer transaction in references/stacks.md.

  1. Final writing gate — List every promised or required artifact. Write each artifact. Read each artifact back. Follow references/durable-writes.md. Stop if a required write is missing or unverified.
  2. Validate — Run the repository’s quality gate. Use just check in easy-cheese or any repository that defines it. Do not commit or publish when the quality gate fails.
  3. Inspect — Read the status, complete diff, and recent log. Verify the intended file set.
  4. Stage — Add only named files. Do not stage the full tree. Keep temporary .cheese/ reports unstaged. Include tracked wiki and documentation changes. If the repository has a Hallouminate wiki, inspect git status for uncommitted .hallouminate/wiki/ paths. Include writes from earlier in the session. Stage these writes unless Git ignores them. Publish wiki updates with this transaction. Do not publish them later.
  5. Commit — Use a Conventional Commit message that explains the reason. Do not amend unless the user requests it. Do not bypass hooks.
  6. Verify — Inspect the status and the committed file set.
  7. Publish when requested — Follow references/ordinary-pr.md. Read the PR after publication. Verify it. Draw any PR diagram by diagrams.md from diagram-templates.md.

Commit-only mode stops after verification. It does not push or open a PR.

Before staging, inspect git status, the complete diff, and recent commits. Reject credentials, .env files, and unexplained large binaries. Stage every intended path explicitly. Use this format:

type(scope): short description
Optional body when the rationale needs it.

Write the subject first. Use a neutral tone. State the change first in the subject. Put only required reviewer facts in the optional body. Keep the body short. Omit narrative prose, tone, and slang.

Use these types: feat, fix, refactor, chore, docs, test, and style. If a hook fails, fix the failure. Re-run the writing and quality gates when artifacts change. Re-stage each named file. Create a new commit.

Use a single-quoted heredoc delimiter for multi-line commit messages. This delimiter protects backticks and dollar signs from shell interpolation. Use an optional Co-Authored-By: <name> <email> trailer when the project accepts the harness identity. Otherwise, omit the trailer. After staging, inspect the cached diff. An empty working diff can mean that all changes are staged. Read the cached diff to tell this state from no changes.

Create one commit for each review unit. Use one commit for a single PR and one commit for each stack layer. Do not shape a PR for commit-by-commit review. The system does not track approval for each commit. Quality gates usually run only on the branch tip. Feedback on one commit delays the other commits. Use multiple commits in one PR only for a short series of simple steps. Keep the combined change small.

Every halt names the mode, the failed step, and who owns the failure. Name the step with exactly one of: classify, topology, durable write, quality gate, stage/commit, publish, or terminal validation. Apply the shared voice rules from ../age/references/voice.md in halt and completion reports.

  • Plate-owned — This skill selected an incorrect call shape or route. Examples include a malformed write, stale write, skipped read, or unnamed staging path. A full-tree staging path is also Plate-owned. A mismatch between the mode and reference is also Plate-owned. Review work for /age or GitHub work outside publication is a Plate-owned routing error. Use this recovery rule: Fix the call shape or the routing, then retry that step.
  • Environment-owner — Authentication, permission, hooks, network, provider enablement, or a shared backend caused the failure. Name the owning system in the report. Never retry it as if the call shape were wrong. Also, never weaken a gate, stage unnamed paths, or skip read-back to bypass the failure.

A failed quality gate proves that the work is not shippable. Therefore, halt at quality gate. Then fix the work.

Write the terminal evidence to a temporary JSON file. Run python3 skills/plate/scripts/plate.pyz validate-publication <state.json>. Report completion only when the command returns normalized evidence with valid: true.

{
"mode": "new-pr",
"topology": "single",
"provider": "ordinary",
"artifacts": [
{"target": "docs/adr/example.md", "backend": "tilth", "verified": true}
],
"gate": {"command": "just check", "result": "pass"},
"commits": ["0123456789abcdef0123456789abcdef01234567"],
"pr_plan": {
"contract_version": {
"schema_uri": "https://schemas.easy-cheese.dev/pr-plan",
"major": "1",
"minor": "0"
},
"shape": "single",
"target_branch": "main",
"groups": [
{
"branch": "feature",
"title": "docs: example ADR",
"base": "main",
"commits": ["0123456789abcdef0123456789abcdef01234567"],
"depends_on": []
}
]
},
"prs": [
{
"url": "https://github.com/example/repo/pull/42",
"base": "main",
"head": "feature",
"verified": true
}
],
"risk": "none"
}

Use empty commits or prs lists when the selected mode does not create them. Topology preflight stops before the publication transaction and quality gate. Therefore, use gate: {"command": "n/a", "result": "n/a"} for topology preflight.

See the generated bundle command inventory in references/commands.md.

scripts/render_generated_regions.py generates this file from the static COMMANDS manifest in src/easy_cheese/skills/plate/commands.py. Do not edit this file. Run each command as python3 skills/plate/scripts/plate.pyz <command> [args...]. Each command returns an integer exit status. Pass --help to a command for its arguments and output format. Keep worked examples in the skill instructions.

Command Purpose Subcommands
carve-flat Emit the branch-carving commands for an orthogonal_flat pr_plan
check-pr-body Check a drafted PR body against the mechanical body rules
gh-stack-preflight Validate the gh-stack trunk and origin branch before mutation
gh-stack-run Run one gh-stack mutation and reject warning-only success
gh-stack-verify Verify exact gh-stack PR and remote stack publication state
stack-tools Detect supported stacked-PR providers without mutating the repository
validate-publication Validate terminal publication evidence
wheypoint-resolve Resolve a phase slug through the shared Wheypoint kernel (JSON out)

Write every promised artifact. Read each artifact back. Do not publish before both steps finish. Also write each durable fact that you find during implementation. Read each fact back.

Build one list of required artifacts. Include handoffs, specifications, promised reports, generated files, ADR decisions, domain-model decisions, and release notes. Include architecture, convention, protocol, or gotcha knowledge that you find during implementation. Classify each item as required or optional. Classify each item as tracked or transient.

When the repository has a hallouminate wiki, sweep git status for uncommitted .hallouminate/wiki/ paths. Add each non-gitignored path as a required tracked artifact. Wiki writes from earlier in the session ship with this publication.

  1. When the consumer repository exposes a hallouminate wiki, invoke the explicit user-visible /wiki-ingest handoff/capability. Do not duplicate its curation algorithm or hand-edit .hallouminate/wiki.
  2. If hallouminate or /wiki-ingest is unavailable, write the tracked fallback from skills/mold/references/adr.md: docs/adr/<slug>-NNN.md. A cumulative domain model uses the repository’s existing tracked domain-model path.
  3. Other promised tracked artifacts go to their contractually named paths.
  4. .cheese/ reports are transient evidence. Keep them unstaged.

Run these three calls in order for each tracked file:

  1. Fresh tagged read — Read the target immediately before writing. Copy its tag and 1-based line numbers from that read. Never reuse a tag, a line number, or a file body captured earlier in the session.
  2. One stale-safe write — Send one write with that fresh tag. Use the operation shape that the backend defines. A text replacement carries only the exact unique old string and its new replacement—never start/end line numbers. Line operations carry only integer start and end values from the fresh read. Mixing the two op shapes is a malformed write. It is a call-shape defect owned by this skill, not a backend outage.
  3. Diff read-back — Re-read the written range or diff the file. Compare the target, essential contents, and expected revision. Then mark the row as verified.

A rejected write means the file drifted. Read the file again for a new tag. Then retry that section. After a rejection, never retry with the stale tag. Also, never fall back to a shell redirect or a host editor.

Read back every required write from the same backend. Compare the target, essential contents, and expected revision. Emit one completion row per item in the exact shape {target, backend, verified}. Set verified to true only after a successful read-back.

Halt before just check, staging, commit, push, or PR creation if a required write is missing. Also halt if a write fails or a read-back cannot verify it. Report optional write failures. Never mark them as complete.

Put shared tracked knowledge on the bottom/common branch or an explicit wiring branch. All dependent PRs must inherit that branch. Put PR-specific artifacts on the branch whose behavior requires them. The completion rows must name that placement before you submit the stack.

When --hard is active, pass one JSON context into /hard-cheese before publication. The context requires four fields:

Field Value
artifacts The completion rows in the exact shape {target, backend, verified}
inventory The final required and optional artifact list
tracked_diff_digest The digest of the tracked artifact diff at the reviewed state
gate The quality gate command and its result

Halt when a field is missing. Halt when a row is unverified. Compute tracked_diff_digest from the reviewed tracked tree. Do not reuse a digest from an earlier state.

Use this provider only when github/gh-stack is installed and the enablement preflight reports available. Run every command from the repository root.

Run gh stack --version and gh stack <command> --help before the first mutation. The verified command surface adopts existing branches through positional arguments. Do not use the deprecated hidden init --adopt flag. The installed init command has no --prefix or --numbered flags.

Resolve the intended GitHub branch name. The default branch query gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' returns a name such as main. Do not pass a remote-tracking value such as origin/main or refs/remotes/origin/main to --base.

Run the executable preflight before init, link, or any recovery mutation:

Terminal window
python3 skills/plate/scripts/plate.pyz gh-stack-preflight \
--trunk <github-branch-name> --remote origin

The preflight canonicalizes refs/heads/<name> to <name>, validates the Git branch name, requires the origin remote, and confirms the exact refs/heads/<name> branch on that remote. Halt at publish when it fails.

Initialize one or more new or existing branches in bottom-to-top order:

Terminal window
gh stack init --base <trunk> <bottom> [<next> ...]

Existing branches are adopted automatically. Add a new top branch with gh stack add <branch>. Do not use combined staging or commit flags. Stage named paths and create normal commits before branch operations.

Inspect with gh stack view --short or gh stack view --json. Resolve local tracking paths from GIT_DIR="$(git rev-parse --git-dir)". Tracking lives at $GIT_DIR/gh-stack. Rebase recovery state lives at $GIT_DIR/gh-stack-rebase-state. Git does not track either path.

The extension can print ⚠ warnings for failed PR or stack API calls and still exit zero. A zero exit is therefore provisional. Run mutations through Plate’s guard so a warning, HTTP failure, or non-zero exit fails publication:

Terminal window
python3 skills/plate/scripts/plate.pyz gh-stack-run -- \
gh stack <operation> <arguments>

The guard requires explicit --remote origin for submit, push, sync, rebase, and link. The installed init, add, modify, and unstack commands do not support --remote; do not add it to those commands.

Resolve every title and body before publication. Submit the complete chain:

Terminal window
python3 skills/plate/scripts/plate.pyz gh-stack-run -- \
gh stack submit --auto --open --remote origin

Here --auto skips only the provider editor. It does not override Plate’s explicit topology or review-shape policy. Omit --open when the requested PRs must remain drafts.

Use guarded gh stack push --remote origin only to update existing branches without PR metadata changes. Never use a bare single-branch push.

After submit, push, or link, run terminal validation:

Terminal window
python3 skills/plate/scripts/plate.pyz gh-stack-verify \
--trunk <github-branch-name> --remote origin

The verifier skips a contiguous run of merged or queued layers at the bottom of the stack and reports them as skipped. It validates every layer above that run. The first open layer’s base must be the trunk. A merged or queued layer above an open layer fails verification.

The verifier fails unless all of these facts match exactly:

  • The local stack trunk equals the canonical GitHub branch name.
  • At least one open layer remains above the skipped layers.
  • Every open branch exists at the same local, remote, and PR head SHA.
  • Every open PR is open, has auto-merge disabled, and has the expected base and head.
  • Every open PR maps to the same open GitHub stack.
  • The remote stack base, ordered PR numbers, head refs, states, and SHAs match for the open layers. The skipped layers keep their head refs, in order, at the bottom of the remote mapping.

Treat any failed check as a failed publication even when gh stack exited zero.

  • Install with gh extension install github/gh-stack.
  • Upgrade with gh extension upgrade gh-stack.
  • Use full gh stack commands. Do not assume the optional gs alias.
  • Authenticate through gh auth login. The extension uses OAuth.
  • Detect installation via gh extension list.
  • Resolve all local metadata with git rev-parse --git-dir.

GET /repos/{owner}/{repo}/stacks is a read-only preflight; run it before the first stack mutation instead of discovering enablement from a failed write.

Terminal window
gh api --include "repos/{owner}/{repo}/stacks"

Classify the response by HTTP status, not by process exit:

Status Meaning Response
2xx Stacked PRs enabled Proceed with the provider
404 Repository enablement requirement Halt and report that Stacked PRs must be enabled
401, 403 Authentication or authorization failure Halt and report authentication or authorization
other Service failure Halt and preserve the status and stderr
none Indeterminate repository or network failure Halt and report the unresolved remote check

python3 skills/plate/scripts/plate.pyz stack-tools runs this preflight. It reports available, not-enabled, auth-required, service-error, remote-check-required, or not-installed. Proceed only with available. The report preserves http_status, exit_status, and stderr.

Need Installed command
Initialize or adopt gh stack init --base <branch> <branches...>
Add top branch gh stack add <branch>
Inspect gh stack view --short or gh stack view --json
Pull collaborator stack gh stack checkout <PR-or-branch>
Push branches only gh stack push --remote origin
Create or update PRs gh stack submit [--auto] [--open] --remote origin
Sync remote and local state gh stack sync --remote origin
Cascade local rebase gh stack rebase --remote origin
Reorder, drop, rename, or fold gh stack modify
Link existing branches or PRs gh stack link --base <base> --remote origin <items...>
Remove stack tracking gh stack unstack [<stack-number>] [--local]
Navigate gh stack up, down, top, bottom, trunk, or switch

submit --auto defaults new PRs to draft. --open marks new and existing PRs ready for review. push changes branches without PR metadata. link creates the server relationship without adopting local tracking.

The installed extension defines these codes. Warning-free exit zero still requires terminal validation.

Code Meaning Response
0 Command returned without a typed error Reject warnings, then verify exact state
1 Generic or already-reported error Preserve stderr and halt
2 Branch or stack not found Re-detect or adopt; do not emulate
3 Rebase conflict Use provider recovery
4 GitHub API failure Preserve the API error and halt
5 Invalid arguments or flags Read installed help, correct input, and retry once
6 Disambiguation required Select the intended stack or remote
7 Rebase already active Continue or abort the provider operation
8 Stack lock acquisition failed Wait; do not mutate concurrently
9 Stacked PRs unavailable Halt and report repository enablement
10 Interrupted modify requires recovery Continue or abort gh stack modify

Unknown non-zero exits fail publication. Preserve the command, code, stdout, and stderr. Then halt.

Resolve each named path after a rebase conflict. Stage each resolved path. Run gh stack rebase --continue or gh stack rebase --abort. Do not run git rebase --continue. The provider must update its recovery state. For modify conflicts, run gh stack modify --continue or gh stack modify --abort.

Use this transaction when local tracking or published PRs use the wrong trunk. Preserve PR identity when the stack is safe to rebuild.

  1. Stop publication. Save gh stack view --json, the remote stack response, every branch SHA, and every PR’s number, base, head, state, draft state, autoMergeRequest, and merge-queue state.
  2. Halt for a user decision when any PR is merged, queued, has auto-merge enabled, or is not open. Do not unstack or rewrite those PRs.
  3. Run gh-stack-preflight with the corrected trunk. Halt if it fails.
  4. Run guarded gh stack unstack <stack-number>. Verify each PR remains open with the same number and head. Verify each PR-to-stack query returns empty.
  5. Run guarded gh stack unstack --local only if local tracking remains.
  6. Re-adopt the same branches, bottom to top, with guarded gh stack init --base <correct-trunk> <branches...>. Do not recreate or rename an existing PR.
  7. Submit with guarded gh stack submit --auto --remote origin. Preserve draft state; add --open only when every recovered PR was ready before recovery.
  8. Run gh-stack-verify. Compare every PR number with the saved snapshot.

If unstacking, re-adoption, PR identity, or final mapping differs from the snapshot, halt at publish. Do not create replacement PRs automatically.

  1. Run the trunk and enablement preflights.
  2. Run guarded gh stack init --base <trunk> <bottom>.
  3. Write, validate, stage, and commit the bottom layer.
  4. Run guarded gh stack add <top>. Repeat the transaction for the top layer.
  5. Inspect with gh stack view --json.
  6. Submit through the guard with --remote origin.
  7. Run gh-stack-verify and record every verified PR/base/head pair.

Navigate to the lower layer and create a new commit. Run guarded gh stack rebase --remote origin. Inspect the stack. Use guarded push or submit according to whether PR metadata changes. Then verify publication.

Run guarded gh stack link --base <base> --remote origin <branches-or-PRs>. This command does not adopt local tracking. Verify the remote stack mapping.

Run guarded gh stack sync --remote origin. Inspect the stack. Submit again only when local commits remain unpublished. Then run gh-stack-verify. A native stack keeps its merged layers, so the verifier skips the merged or queued layers at the bottom and validates the open layers above them. A merged or queued layer above an open layer requires lifecycle inspection instead.

Use when git-town is installed and a trunk is configured: the local git-town.main-branch key or [branches] main in a committed git-town.toml. Lineage lives in local git-town-branch.<name>.parent config.

Append --non-interactive to every state-changing Git Town command and supply names, parents, messages, and merge choices explicitly. Use --dry-run first for risky sync or reorganization when supported. If required input is missing, stop and ask; never allow an agent-run command to wait on a prompt.

Start the bottom branch with git town hack <name> --non-interactive and extend with git town append <name> --non-interactive. Stage named paths and create normal new commits; avoid combined all-files or rewrite flags.

Inspect with git town branch. Publish the chain with git town propose --stack --non-interactive. Sync/restack with git town sync --stack --non-interactive; use --no-push only when publication is not authorized. Never push one stack branch directly.

  • Install with brew install git-town, choco install git-town, or scoop install git-town; check git town --version.
  • The git town init wizard (older releases name it git town config setup) is interactive, so only a person runs it. An agent sets trunk directly with git config --local git-town.main-branch <trunk>. A committed git-town.toml (also .git-town.toml or .git-branches.toml) with [branches] main shares the trunk with every clone. Git Town reads only the first of those files that exists, in that order.
  • On GitHub, prefer git-town.github-connector gh to reuse authenticated CLI access; environment tokens are preferable in ephemeral systems.
  • Usability requires the executable and a non-empty trunk from either source. Inspect parents with git config --get-regexp '^git-town-branch\.'.
  • Resolve repository metadata with git rev-parse --git-dir when inspecting git-owned state; never assume a literal metadata path.

Git Town is forge-agnostic. Configure git-town.forge-type when forge auto-detection is wrong.

Need Command
Start bottom from trunk git town hack <name> --non-interactive
Extend current stack git town append <name> --non-interactive
Insert below current git town prepend <name> --non-interactive
Create local-only work add --prototype to hack/append/prepend
Record/change parent git town set-parent <parent> --non-interactive
Detach as perennial git town set-parent --none --non-interactive
Inspect lineage/types git town branch
Read a parent git town config get-parent [branch]
Rename git town rename <name> --non-interactive
Delete git town delete --non-interactive; explicit approval required
Interrupted state git town status --pending

Branch types are feature, prototype, parked, contribution, and observed, stored in git-town-branch.<name>.branchtype. Long-lived shared branches belong in git-town.perennial-branches. Repository defaults may live in git-town.toml; forge/auth settings use git-town.forge-type, git-town.github-connector, and the matching token setting or environment variable.

Prototype branches remain local until proposed. Do not silently convert a prototype to a published feature branch.

Scope or behavior Command
Current branch git town sync --non-interactive
Current stack git town sync --stack --non-interactive
Every branch git town sync --all --non-interactive
Skip trunk/perennial pull-in git town sync --detached --non-interactive
Restack locally without push git town sync --stack --no-push --non-interactive
Prune branches that become empty git town sync --prune --non-interactive
Open/update stack PRs git town propose --stack --non-interactive

Use --all, --detached, and --prune only when their wider scope or deletion behavior is intended and verified.

git town ship --non-interactive merges the current branch through the forge. --to-parent ships into a non-perennial parent; an explicit message can be provided when required. Prefer the forge UI plus git town sync --stack --non-interactive for routine merges. Run ship through Plate only when the user explicitly requested provider-native stack shipping, verify the target and merge strategy, and confirm the installed syntax with git town ship --help.

When sync, propose, or ship halts, inspect git town status --pending. Resolve and stage named paths, then use git town continue, git town skip, or git town undo as directed by the pending operation. A bare git rebase --continue is never correct because it does not advance Git Town’s branch walk.

Git Town can force-update rebased stack branches; coordinate when teammates also write them. Shared durable writes belong on the bottom/common branch or an explicit wiring branch before propose or sync.

  1. Run git town hack <bottom> --non-interactive.
  2. Write common artifacts, validate, stage named paths, and commit.
  3. Run git town append <top> --non-interactive; repeat for top-only work.
  4. Run git town branch to verify parents.
  5. Run git town propose --stack --non-interactive, then verify PR bases.

Sync it, set its parent non-interactively, inspect lineage, append branches if requested, then propose the stack.

Switch to it, create a new commit, then sync the stack non-interactively so descendants and remote PRs follow.

Squash merges can create phantom conflicts because child history no longer matches the merged commit. Configure git-town.auto-resolve or use a compatible merge strategy when the repository accepts it. Confirm version-specific syntax with git town <command> --help.

Use when gt is installed, Graphite tracks the current stack, and test -f "$(git rev-parse --git-dir)/.graphite_repo_config" succeeds.

Graphite is interactive by default. Pass --no-interactive and supply branch names, messages, bases, and reviewers explicitly. If an operation still needs an editor or picker, stop and ask rather than hanging or guessing.

Create branches with gt create <name> without all-files commit flags. Stage named paths, then create a normal new commit. For a tracked branch update, gt modify -c -m "<message>" creates a new commit and restacks descendants. Bare gt modify amends; use it only when the user explicitly requests a history rewrite. Hooks remain enabled.

Inspect with gt log short. Restack with gt restack; sync trunk and prune merged branches with gt sync. Submit the whole chain with gt submit --stack. Its lease-aware push is the publication path; do not push one stack branch separately.

  • Install with brew install withgraphite/tap/graphite or npm install -g @withgraphite/graphite-cli@stable.
  • Check gt --version; use gt upgrade on supported releases.
  • Authenticate with gt auth --token <token>; ephemeral environments prefer GRAPHITE_AUTH_TOKEN.
  • Initialize once with gt init; it records trunk at $(git rev-parse --git-dir)/.graphite_repo_config.
  • The provider is usable only when the executable and resolved marker exist.
Need Command
Start/extend a stack gt create <name>
Adopt an existing branch gt track --parent <parent>
Remove tracking gt untrack
Inspect gt log short or gt ls
Navigate gt up, gt down, gt top, gt bottom
Check out gt checkout <branch>
New commit + restack gt modify -c -m "<message>" after named staging
Restack descendants gt restack
Fetch trunk, prune, restack gt sync
Submit all PRs gt submit --stack
Update open PRs only gt submit --stack --update-only
Preview gt submit --stack --dry-run

Submission may add --draft, --publish, or explicit reviewers. Retain the default lease check rather than selecting true force.

Use Graphite commands so lineage remains correct:

Need Command and rule
Move a branch and descendants gt move --onto <parent>
Reorder gt reorder; user-driven editor only
Split gt split -c, gt split -h, or gt split -f; verify every resulting boundary
Absorb staged hunks downstack gt absorb after named staging; keep confirmation enabled
Fold into parent gt fold; explicit history-rewrite approval required
Squash current layer gt squash; explicit history-rewrite approval required
Remove branch, keep changes gt pop; explicit destructive approval required
Undo last Graphite mutation gt undo; inspect before and after
Delete branch gt delete; explicit branch-deletion approval required

After any split, absorb, move, fold, squash, pop, or undo, inspect gt log short, validate affected layers, and resubmit only after lineage and commit paths match the approved split.

gt get <branch> fetches a collaborator’s submitted stack. Retrieved branches are frozen by default; inspect them without mutation. Use gt unfreeze only after the user confirms ownership/coordination, and gt freeze to restore the read-only collaboration posture. gt get -U opts into immediate editability; never choose it silently.

For repositories with several trunks, add one with gt trunk --add <branch>. Use gt log --all or gt checkout --all for cross-trunk inspection, but select the intended trunk explicitly before creating lineage. Graphite refuses to mutate a branch checked out in another worktree; report that worktree rather than bypassing the refusal. gt undo history is per worktree.

Resolve and stage each conflicted path by name, then run gt continue or gt abort. A bare git rebase --continue is never the recovery path because Graphite must advance its stack metadata. There is no documented gt skip; abort and isolate the branch instead.

  1. From clean trunk, run gt create <bottom>.
  2. Write bottom/common artifacts, validate, stage named paths, and commit.
  3. Run gt create <top>; repeat the per-layer transaction for top-only work.
  4. Inspect with gt log short.
  5. Publish with gt submit --stack and verify every PR/base pair.

Check out the lower branch, stage named paths, create a new commit with gt modify -c, run gt restack, inspect, then gt submit --stack.

Run gt sync, inspect gt log short, then submit only if local commits remain unpublished.

Shared durable writes belong on the bottom/common branch or an explicit wiring branch. Confirm version-specific syntax with gt <command> --help.

Use this path only after the final writing gate, the green quality gate, named-file staging, the commit, and the commit verification. It covers the single shape and the orthogonal_flat shape (independent PRs off the trunk).

  1. Confirm that /plate resolved the new PR as single, or as one group of an orthogonal_flat resolution. Accept an explicit choice or the topology decision.

  2. Resolve the trunk and current branch. Reject publication from the trunk.

  3. Draft a title and body per ## Body contract below.

  4. Write the body to a temporary or transient file. Pass that file through --body-file. Do not embed a markdown heredoc in --body. Then run python3 skills/plate/scripts/plate.pyz check-pr-body --body-file <body-path>. Add --template-file .github/PULL_REQUEST_TEMPLATE.md when the repository tracks that template. Add --stack-layer for a stack layer. Fix every reported error and run the check again. Do not create or edit the PR until the check exits 0.

  5. Push the named branch without force. Follow ## Push verification before the next step.

  6. Create the PR with an explicit base and head:

    Terminal window
    gh pr create --title "<title>" --body-file <body-path> --base <base> --head <head>
  7. Verify with gh pr view --json number,url,title,baseRefName,headRefName,state.

Do not use --fill when it would omit artifact or verification details.

Use this section for the orthogonal_flat shape. Base every group on the trunk. A group has no depends_on. Record the evidence as topology stacked, provider ordinary, and a pr_plan with shape orthogonal_flat. validate-publication accepts provider ordinary with topology stacked only for that plan shape. Emit the carving commands once: python3 skills/plate/scripts/plate.pyz carve-flat --source-branch <source> --pr-plan <plan-path>. The JSON groups list follows plan order. Each entry holds branch, base, carve, and restore. For each group, in plan order:

  1. Run the group’s carve commands. They create the branch from the trunk and cherry-pick its commits in order. When one commit mixes groups, check out the group’s whole files from the source branch and create a new commit instead of the cherry-pick.
  2. Run the quality gate on the group branch. Halt at quality gate for that group when it fails.
  3. Publish the group as a ## New PR. Its body describes only its own group.
  4. Run the group’s restore command before the next group.

Leave the source branch unchanged. Report every PR URL in plan order.

Detect the PR with gh pr view --json number,baseRefName,headRefName,url. Then inspect the provider metadata. A stacked topology leaves this file for stacks.md. Read the base and head with gh pr view. Commit the validated named files. Push the exact head branch. Then read the PR back. Update the title or body only when the new work makes existing metadata inaccurate. To move part of the PR into a separate PR, create a new orthogonal_flat branch from the trunk. Removing that part from the existing branch rewrites published history. It needs explicit user authorization.

Authentication or permission failures halt publication. Report the exact command and error. A rejected push does not permit a force-push. Fetch and explain the divergence. Never create a duplicate PR when one already exists.

Publication-relevant GitHub operations remain here:

  • Add --draft when explicitly requested.
  • Add --reviewer <login> or --assignee <login> only from the supplied publication metadata.
  • Use gh pr edit <number> --title <title> --body-file <path> when verified commits make existing metadata inaccurate. Run check-pr-body on that file first.
  • Use gh pr ready <number> only when asked to publish a draft.
  • Use gh pr checks to verify publication context. CI triage, review, comments, and merge stay outside /plate. Use the gh CLI directly for that work.

Query the current head for an existing PR before creation. If a PR exists, switch to the existing-PR path. Do not rely on a failed create call.

A reviewer reads a short body. Agent-written bodies that claim changes the diff lacks lose reviewer trust. When the repository tracks .github/PULL_REQUEST_TEMPLATE.md, use its section headings. Otherwise use ## Why, ## What changed, ## Non-obvious changes, ## How to verify, and ## Risk. check-pr-body enforces the 40-line cap, the required headings, the Plated as line, the filler-word ban, and, for a stack layer, the Stack: <n> of <total> line and the stack-order flowchart. The 20-line cap for a small change, the claims, and the reading order stay a judgment call. Keep the body file transient unless the repository tracks PR templates or release artifacts. Leave a transient body file unstaged after verification.

Length and tone:

  • Count non-blank lines. Do not count one diagram or the checklist of a repository PR template.
  • Keep the body at 40 lines or fewer. Keep a small change at 20 lines or fewer.
  • Give each prose section one to three sentences or bullets. Write None for an empty template section.
  • Open with why in one or two sentences.
  • Do not restate the diff or list every file. When the change exceeds about 200 lines or 5 files, give a reading order.
  • Use plain words. Do not use filler such as comprehensive, robust, seamless, leverage, significantly, or dramatically.
  • Rewrite a supplied draft body. Keep only the facts that the evidence supports.

Claims:

  • Name a change only when the net diff contains it. A reverted commit is not a change.
  • List each verification as one line: the command and its result (pass, fail, or not run). List only checks that ran in this session. List a relevant check that did not run as not run. Never claim a benchmark, platform, harness, or speedup that no command measured.
  • Link the spec, plan, or spike branch, and list deferred follow-ups, when they exist.
  • A semantics-preserving change says so in its first line. It names the mechanism and states the invariant to verify. Examples include a behavior-preserving refactor, an internal move, an internal rename, or a formatting-only change. For example, a move states that it drops nothing and duplicates nothing.
  • A semantics-altering change names the changed behavior or contract and its observable verification. A logic change names the test that fails before the change.
  • A ## Non-obvious changes section names every hunk whose intent is not visible from the diff alone, with one line of reason each. Write None when every hunk is self-evident. Author-annotated reviews carry markedly lower defect density (Cisco review data).
  • List generated files, such as .pyz archives and lockfiles, as generated. Tell the reviewer to skip them.
  • Add the topology line Plated as <shape>: <reason>. A stack layer adds Stack: <n> of <total>, with the PRs below and above it. An independent PR does not describe the other groups.
  • State size risk, a weakened check, or a landing-shape deviation under the risk section.

Add one Mermaid diagram at most, and only when the structure is the point of the review. Pick it with the checklist and the smallest-set rules in diagrams.md. When several items apply, draw the one that shows the riskiest change.

Add no diagram to a small fix, a docs-only pull request, or an independent PR. A stack layer keeps a flowchart of the stack order, with this PR marked. Derive the diagram from the diff. Show only the elements that the diff changes, plus their neighbors. Draw it by the notation and Mermaid rules in diagrams.md.

Read the remote and upstream before pushing. Push the exact named head branch. Do not pipe git push into another command; a pipe hides its exit status. Read the exit status. Then confirm the remote head with git ls-remote --heads <remote> <branch>. The remote head SHA must equal the local head SHA before gh pr create. A failed or unverified push halts at publish. An authentication failure is environment-owned. Verify local status. Verify the PR head and base. A successful CLI exit without a matching PR head SHA is incomplete.

Load this reference from stacks.md when no stack provider is usable, or when the user asks how to set up a provider for a team or a new machine. Give the user the steps for the selected provider. Do not run install, login, or init commands without approval.

Each provider keeps configuration in one of three scopes. Only shared scopes reach a teammate or a second machine.

Scope Location Shared with teammates Repeat on a new machine
User Home directory No Yes
Clone $(git rev-parse --git-dir), never committed No Yes, once per clone
Shared A committed file or GitHub server state Yes No
Graphite (gt) Git Town gh stack
Account per CLI user Graphite account None None beyond GitHub
User-scope auth gt auth --token <token> gh connector or a token gh auth login
Repository config gt init writes .graphite_repo_config in the git dir git town init writes git-town.toml None; GitHub holds the stack state
Config scope Clone Shared, after commit Shared, server-side
Init on each clone Yes No No
Reviewer tooling None None None

Stacked pull requests are ordinary GitHub pull requests. Reviewers need no provider CLI or account.

Each CLI user needs a Graphite account. A reviewer does not.

  1. On each machine, install gt and run gt auth --token <token>. Ephemeral hosts set GRAPHITE_AUTH_TOKEN instead.
  2. In each clone, run gt init. The command records trunk in the git dir. Nothing is committed, so every teammate and every clone repeats this step.
  3. To work on a teammate’s stack, run gt get <branch>.

Graphite plans and open-source terms change. Tell the user to confirm organization-repository access with Graphite before the team adopts it.

Git Town needs no account and no server.

  1. One maintainer runs the interactive git town init wizard once and saves to a config file. The maintainer then commits git-town.toml. An agent never runs the wizard.
  2. On each machine, each teammate installs git-town and sets forge access: git config --global git-town.github-connector gh reuses gh login. A token in git-town.github-token or GIT_TOWN_GITHUB_TOKEN also works.
  3. A clone reads the committed trunk. It needs no init.

Keep forge tokens and the connector choice out of the committed file.

Stacked pull requests are a GitHub public preview. GitHub opened the preview to all github.com repositories on 2026-07-30, so no access request is needed.

  1. On each machine, run gh extension install github/gh-stack and gh auth login.
  2. A clone needs no init. GitHub holds the authoritative stack state.

The enablement preflight in gh-stack.md still decides for this repository. A 404 means Stacked PRs is not available to it. Stacks cannot be driven from a fork.

Load this reference for the stack maintenance mode. Also load it for any new or existing pull request whose resolved shape is stacked_linear or diamond_stack. Ordinary single pull request work never reads this file.

  1. Select the configured provider. Then read its reference.
  2. Use the layer boundaries that topology resolved: an explicit choice, the landing block, or the clean parts from topology.md. Partition paths and commits by layer. Place shared durable writes on the bottom/common layer or an explicit wiring layer. Classify the production implementation decision. Tests, docs, and durable artifacts inherit its layer. They inherit the layer when they directly verify or describe the decision. Each layer’s implementation preserves semantics or alters them, never both. Each layer’s pull request body follows ordinary-pr.md § Body contract, including ## Non-obvious changes and the stack position line. A stack layer always carries the stack-order diagram. Check each layer body with check-pr-body --stack-layer before the provider creates or edits the PR. Put semantics-preserving layers below the semantic changes that depend on their reorganization.
  3. Create or adopt provider lineage in the approved bottom-to-top order.
  4. Read the spec’s landing.per_layer_green before publishing any layer. required (the default) means every layer’s quality gate must pass before the next layer is published. tip-only means only the top layer’s gate must pass before the chain is submitted; a lower layer’s gate failure does not block it.
  5. For each layer, bottom to top:
    1. Check out its provider-tracked branch.
    2. Run the final writing gate for that layer. Then read every write back.
    3. Run the repository quality gate.
    4. Inspect the layer diff. Then stage only its named paths.
    5. Create a new Conventional Commit without skipping hooks.
    6. Verify the commit’s paths and the layer’s parent.
  6. Inspect or restack the complete chain through the provider.
  7. Submit the complete chain after you verify all layers.
  8. Read back every PR, base and head pair, and provider stack map.

Never manufacture split boundaries. Never move a shared artifact to a convenient upper layer. Never submit a partially verified chain.

Resolve metadata through GIT_DIR="$(git rev-parse --git-dir)". Never assume that the repository metadata directory is the literal .git path.

Provider Installed Repository signal Reference
Graphite gt --version $GIT_DIR/.graphite_repo_config gt.md
Git Town git town --version git-town.main-branch config or a committed git-town.toml trunk git-town.md
gh stack gh extension list contains github/gh-stack gh api --include "repos/{owner}/{repo}/stacks" preflight gh-stack.md

Use the stack-tools report on every invocation. Preserve the provider that already tracks the branch. When no provider tracks it, use the report’s recommended provider. State the choice. A not-installed provider with repository_signal: true is configured for this repository. Name the missing executable when you choose another provider or stop. Only a gh-stack status of not-enabled (preflight 404) is a repository enablement requirement. Other non-available statuses are environment failures. When the preflight is indeterminate, a remote operation’s exit code 9 is the fallback enablement signal. Exit code 4 is a generic GitHub API failure, not an enablement signal. Stop with setup instructions when no provider is usable after you select stacked. Take those instructions from setup.md. Do not emulate stacking with plain pushes.

Use gh pr view --json number,baseRefName,headRefName,url to detect the PR. Then inspect the provider metadata. Use the per-layer transaction when the topology is a stack. Use the provider submission process. Never use a bare single-branch push inside the stack. An ordinary PR uses the generic transaction and ordinary-pr.md instead.

Run a provider-native stack merge in /plate only when the user explicitly requests the merge. Require explicit user authorization for a force-push outside a provider’s lease-safe stack flow.

Load this reference for the topology preflight and new PR modes. It resolves only the review shape. Execution continues in ordinary-pr.md for single and orthogonal_flat, or in stacks.md for stacked_linear and diamond_stack.

Plate decides the review shape. It does not ask the user. Resolve the shape before any commit or branch-layout mutation.

  1. Honor an explicit user choice from the current request, verified workflow state, or the spec’s landing block. It is authoritative. Derive the topology from landing.shape via easy_cheese_schemas.manifest.plate_layout_for, with landing.layers as the proposed layer boundaries. A landing.shape of diamond_stack is allowed only when an explicit choice names it. A choice of shape without boundaries (“make this a stack”) still needs boundaries. Derive them with step 3. When step 3 finds no clean boundary, apply the conflict rule below: collapse to single and state the deviation.

  2. Classify each production change:

    • Use semantics-altering for features, fixes, or externally observable contract changes.
    • Use semantics-preserving for behavior-preserving refactors, internal moves, internal renames, or formatting-only changes.
    • A diff containing both is never one review unit. Preserved behavior and changed behavior require different review scrutiny.
    • A move or rename is semantics-altering if it changes an externally observable name, path, API, or configuration key. Use the same classification for a changed serialized shape, command, or documented contract.
  3. Partition the work into parts. A part is a set of commits or whole files with one purpose. A part becomes one pr_plan group and one stack layer. Use only existing commit boundaries or whole-file partitions. Never manufacture a boundary that splits a hunk or rewrites a commit. Merge parts that edit the same hunks into one part. This rule overrides a spec that asks for one PR per issue. State why. Tests, docs, and durable artifacts join the part whose decision they verify or describe. A generated artifact, such as a .pyz archive or a lockfile, joins the part whose source generates it. An incidental fix that is unrelated to the main change is its own part.

  4. Choose the first row that matches:

    Evidence Shape
    One part: one cohesive review unit that serves one behavior or contract single
    A split needs a history rewrite, or a lower part fails the quality gate alone single
    Two or more parts that share no file, import, or configuration, and each applies to the trunk alone orthogonal_flat
    Ordered parts where each later part depends on an earlier part, and each part passes the gate on its parent stacked_linear
    Independent parts mixed with a dependent chain stacked_linear for the chain. Publish each independent part through ordinary-pr.md § Independent PRs, and exclude it from the stack partition
    Any other case, such as independent parts that share a file without hunk overlap single; name the shared file in the reason

    Put a semantics-preserving part below the semantic change that depends on its reorganization. Never stack parts that do not depend on each other. Independent parts merge and revert alone.

  5. Size never decides the shape on its own. When the semantics-altering surface exceeds roughly 400 changed code lines, look again for clean boundaries. Reviewer defect detection falls off sharply past that size (SmartBear/Cisco review data). With no clean boundary, choose single. State the size risk in the PR body and give a reading order. At topology preflight, before a diff exists, estimate the parts from the spec or curd plan. At publication, reuse the preflight result. Decide again only when the real diff breaks the preflight parts.

  6. Record the decision as one line in the completion report and the PR body: Plated as <shape>: <reason>. Proceed without asking.

A landing block that the finished diff cannot meet does not stop publication. A layer that depends on files a later layer owns, or commits that cannot split on the layer boundaries, is a conflict. Re-layer on the clean boundaries from step 3 when they exist. Otherwise collapse to single. State the deviation in the PR body. The statement names the layer and the files in conflict. Record the same statement in the deviation field of the publication evidence. validate-publication accepts a single plan against a multi-PR landing only when deviation is non-empty. When landing and pr_plan are both present, their shapes must otherwise match.

A supplied pr_plan is evidence for the decision. It can provide explicit commit and file boundaries. It cannot override an explicit user choice or another verified topology resolution. Repair a malformed plan instead of halting: map a legacy stacked shape to stacked_linear and add the v1 contract_version block. Keep the plan’s groups, branches, and bases when they satisfy step 3.

A prior /plate topology preflight for the same run is the resolution. Reuse it. Do not decide twice. Persist plate_layout: single | stacked and the chosen shape in workflow state. stacked covers every multi-PR shape. Choose the pr_plan shape from this resolution: single, orthogonal_flat, or stacked_linear. Choose diamond_stack only when an explicit landing.shape names it. plate_layout_for projects plate_layout from shape, not the other way. The v1 plan never carries plate_layout. At terminal publication, verify that both values agree. Apply this policy again when the record is missing, conflicting, or unverified.

For an Existing PR, detect its ordinary or stacked topology. Preserve that topology. Use its matching update path. A request to move part of an existing PR into a separate PR creates a new orthogonal_flat branch from the trunk. Removing that part from the existing branch rewrites published history, so it needs explicit user authorization. Commit-only isolated workers do not decide topology because publication is out of scope.

Topology preflight persists the resolution. It reads the resolution back. It stops before any commit, branch mutation, push, or PR operation.

The branch name is worktree-agent-repair-*. Apply the policy above to any other branch.

The repair handoff must carry run_branch. This field names the verified run branch. Halt at topology when run_branch is absent. A missing field is not evidence of a deleted branch.

Then run the mechanical file-overlap check. See ../../cook/references/quality-gates.md § Repair pathway. Compute the overlap with one command:

Terminal window
git diff --name-only --find-renames "$(git merge-base <run-branch> <repair-branch>)" <repair-branch>

Compare that path set with the same command run for <run-branch>. The shared paths are the overlap. Count the changed lines of each shared path with git diff --numstat over the same range. Count a rename as its changed lines only. Count a binary path as one changed line. Halt at topology when --numstat reports - for a path that is not binary.

Then select the topology:

  • Publish an ordinary independent pull request against main when there are no shared paths.
  • Verify branch deletion with git rev-parse --verify <run-branch> before you use the independent path for a missing run branch. Halt at topology when the command cannot decide.
  • Move shared files onto the run branch at or below the small-repair threshold. Do not publish these files independently. Cook owns the harvest command. Run the harvest through /cook. See ../../cook/references/quality-gates.md. Resolve <run-worktree> from verified Git worktree state. Halt at topology when the harvest fails.
  • Restack with the repair as the base pull request above the threshold. Use the stack process in stacks.md.