AGENT SKILL

cw-land

Use when turning verified Codewhale work into commits on main and pushing them, or merging a contributor PR: staging only your paths, the pre-push drift checks, preserving contributor credit, and honoring the gate artifact before merging.

License 许可
MIT
最近更新
2026-11-12
Stars
★ 4.1w
Forks
3.6k

01 前言 Front Matter

name
cw-land
description
Use when turning verified Codewhale work into commits on main and pushing them, or merging a contributor PR: staging only your paths, the pre-push drift checks, preserving contributor credit, and honoring the gate artifact before merging.

03 SKILL.md 正文

cw-land

Verified work still has to land without stepping on other writers, losing contributor credit, or merging past a gate that has not actually passed. This stage is about the boundary between "it works" and "it is in main" — and about which of those steps you are allowed to take.

Stage 5 of the loop: cw-orient → cw-slice → cw-gates → cw-dogfood → land → cw-handoff.

When to use

  • The change is verified and needs to become a commit on main.
  • You are landing someone else's PR, harvesting a contributor's work, or resolving a conflict caused by main moving.
  • You are about to merge something behind a required gate.

Workflow

  1. Land on main. AGENTS.md owns this: work in your own short-lived worktree, rebase onto origin/main, push HEAD:main, then remove the worktree. No maintainer PR branches, nested clones or integration lanes. Several agents share the checkout, so partition by file, check git status before staging, stage only your paths (never git add -A), and retry a commit that fails on index.lock. Push verified main directly. Every push to main starts full hosted CI on that commit through the landing gate (main-landing.yml): never add [skip ci], watch the run and repair what it finds. PRs are for contributors.

  2. Commit narrow and build-green. One coherent change per commit; the tree builds at every commit. Put the real verification in the message — actual pass/fail counts, not "tests pass".

    Before every push, run the cheap drift checks that have turned a green main red most often. They take seconds:

    cargo fmt --all -- --check
    bash scripts/release/check-versions.sh
    

    The runtime-contract budget checker starts a native Cargo build by default; it is not a cheap drift check. Use an applicable existing measurement with --receipt, or run a new measurement through the required build-lock and SSD cache workflow when the changed contract or final validation needs it. Add the one that matches what you touched: check-tui-locale-parity.py and check-tui-product-vocabulary.sh (locale strings), check-dead-code-budget.py (#[allow(dead_code)]), check-blocking-calls-budget.py (async code), check-readme-translations.py and check-readme-locales.sh (READMEs), node web/scripts/derive-facts.mjs && node web/scripts/check-facts.mjs (public facts and agent docs, which embed the docs), and node web/scripts/check-runtime-routes.mjs --write (a Runtime API route added or removed). Regenerate those two files after every rebase or cherry-pick, even a clean one: git can merge docs/RUNTIME_ROUTES.md wrongly with no conflict marker. Put a new CHANGELOG entry at the top of [Unreleased]. Open contributor PRs append at its end, and an entry of ours there conflicts with every one of them.

    Record it in the same commit. A user-visible change, usually a feat or fix but also user docs, help text, defaults or security behavior, carries its line at the top of the matching [Unreleased] section (Added, Changed or Fixed): what changed for the user, what is still unproved, (#N) for a public issue or PR (never an internal tracker id), and for reported or contributed work Thanks [@handle](https://github.com/handle). Tests, CI, refactors and internal docs need no line. Work by someone outside the maintainers also goes on the three credit surfaces in that commit: the CHANGELOG ### Contributors block, docs/CONTRIBUTORS.md, and UNRELEASED_CONTRIBUTORS in web/lib/release-credits.ts. A contributor PR merged as itself gets that commit right after the merge. Before the push:

    sh scripts/sync-changelog.sh                 # regenerates crates/tui/CHANGELOG.md
    python3 scripts/check-contributor-credit.py  # since the last tag
    git log --format='%h %s' "$(git log -1 --format=%H -- CHANGELOG.md)"..HEAD | grep -E '^[0-9a-f]+ (feat|fix)'
    

    The last command must print nothing for commits you are landing. check-feature-release-notes.sh covers only issue-linked feat commits; fixes slip past it. A catch-up "changelog: record landed work" commit is the failure this step prevents, not the routine.

  3. Preserve credit mechanically, not just politely. GitHub reads neither .github/AUTHOR_MAP nor .mailmap for the contribution graph, so authorship must use the contributor's own GitHub-linked address; those files are project conventions on top. When a contributor's work lands as our commit, the contributor is its author and it carries the harvest line (AGENTS.md, "Harvested contributor credit"):

    git commit --author="Name <ID+handle@users.noreply.github.com>" ...
    
    Harvested from PR #N by @handle
    
    Co-authored-by: <maintainer or agent identity>
    

    GitHub's contributor list counts authors only, and check-contributor-credit.py flags a harvested handle who is not credited. Resolve the address from .github/AUTHOR_MAP, else gh api users/<handle> --jq '"\(.id)+\(.login)@users.noreply.github.com"'. A clean cherry-pick keeps the author by itself. This step is the single owner of credit mechanics; other skills link here. Close their PR by hand with a thank-you naming the commit; nothing closes a PR automatically. Canonical human identities live in .github/AUTHOR_MAP.

    Whether a bot or agent also appears in a trailer no longer matters — the CI check that policed trailer identities was removed because it rejected ordinary agent commits. Give humans their credit; don't spend time scrubbing tool trailers.

  4. Landing someone else's work: their time is more expensive than ours.

    • Never make a contributor rebase around our churn. If their PR conflicts only because main moved, a maintainer resolves it.
    • Read their diff against the merge base first, so you know exactly what they added, then re-apply that — rather than hand-merging two large sides and hoping:
      git diff $(git merge-base main <pr-head>)..<pr-head>
      
    • Conflicts that split mid-function do not resolve by keeping both sides. Git's markers can land inside a body, so a both-sides resolution produces unbalanced braces that look plausible and do not compile. Default: take one side whole, then re-insert the other side's additions at their original anchor; when the conflict doesn't fit that pattern, resolve it however is correct and let the compiler judge.
    • Resolve on their branch without creating a local branch. Build the merge commit with git merge-tree --write-tree origin/main <pr-head> and git commit-tree <tree> -p <pr-head> -p origin/main, then push it with git push <fork-url> "${sha}:refs/heads/<their-branch>". In zsh, write ${sha}, not $sha:refs, because :r is a history modifier. maintainerCanModify does not guarantee that the push is accepted. When the fork refuses it, ask on the PR. Harvesting is the last resort.
    • Check for runs awaiting approval before assuming a PR is stalled. A first-time contributor's workflow runs can sit at action_required until a maintainer approves them, so the PR looks abandoned when nobody has actually looked at it. Approve the runs.
  5. Merging under a gate. AGENTS.md ("Merging under a gate") owns this: the artifact must literally say PASS, the review thread outranks the check rollup, and ambiguity blocks the merge — never the reverse. Before you merge, list the open PRs whose base is the PR's source branch (gh pr list --base <branch>) and retarget them first. Otherwise they close when that branch goes away.

Red flags / don't

  • Don't tag, create a release, publish, or deploy without explicit authorization. Pushing verified main is allowed; it is none of those.
  • Don't rewrite published history, retag a release, or force-push a shared ref.
  • Don't commit AGENTS.md / CLAUDE.md operator controls that live outside the product repository into a public repo.
  • Don't stage another writer's dirty files to get a clean commit.
  • Don't merge on a green rollup alone when a review thread has open findings.
  • Don't harvest or close from a PR title or label — review the code, tests, comments, and checks.
  • Don't add another legacy call site for convenience once a replacement architecture is adopted. Declared migrations are one-way.
  • Don't leave new enforcement live: keep it dry-run/advisory unless approved.

Output

  • Commit SHAs, the paths committed, the drift checks run, and the resulting origin/main SHA.
  • The credit trailers applied and to whom.
  • The CHANGELOG line and credit-surface entries added, or why none was owed.
  • The Linear/GitHub status written after the push, or why none was owed.
  • The gate artifact's literal verdict at merge time, if a gate applies.
  • Exactly which public actions you took, and which you deliberately did not.

04 同仓库更多 Skills