Follow-up from #4867 (the pr-flow skill), which merged with its first acceptance criterion unmet: nothing fails a PR with an unsigned commit today. No DCO check ran on #4904, #4905 or #4906.
The original plan was to install the probot DCO app, but the org appears to have turned it off. The Inspector hit the same thing (modelcontextprotocol/inspector#2566), where the app was suspended and its check quietly disappeared. As there, we replace the third-party app with a check we own.
Scope
- A DCO job in CI. For every commit in the PR's range, require a
Signed-off-by: Name <email> trailer whose name and email match the commit's author or committer. Keep the app's two exemptions: merge commits and bot-authored commits. One unsigned commit fails the job, and its output names the commit and the git rebase --signoff repair.
typescript.yml and python.yml run on both push and pull_request, and a push job doesn't know the PR's base. A small separate workflow on pull_request (using github.event.pull_request.base.sha..head.sha, or gh api …/pulls/N/commits --paginate) is cleaner than inferring a merge-base.
- Use
contents: read only, so the job holds no credential and stays outside the SHA-pin rule (verify:action-pins).
- Declare
timeout-minutes, as scripts/lib/workflow-gate.mjs requires of every job.
- If the logic is more than a few lines, put it in
scripts/verify-dco.mjs with a sibling verify-dco.test.mjs, like the other guards.
- Per AGENTS.md, a check added to CI joins
local:gate:stages in the same change. Locally it can check origin/v2/main..HEAD, which also catches an unsigned commit before it is pushed.
- Verify it: push an unsigned commit to a throwaway PR against
v2/main and confirm the job fails. Then repair it with git rebase --signoff and confirm it passes.
- Make it required. Add the job's check as a required status check in a ruleset that covers
v2/main. No ruleset applies to v2/main today, and main's rulesets require no status checks, so this is a repo-admin settings change, not something the PR can do. Consider main too.
- Update the docs, in the same PR as the job:
- add the signoff rule to
AGENTS.md, which only states rules that are true of the repo today;
- rewrite
.claude/skills/pr-flow/SKILL.md step 3 so it describes the new job instead of the probot app: delete the "⚠️ The probot DCO app is not installed on this repo yet" paragraph, and drop the .github/dco.yml / remediation-commit / override-button discussion, which only applies to the app;
- realign the
AGENTS.md skills-index table: the issue-triage and security-advisory rows were added without padding to avoid stacking conflicts.
Acceptance criteria
Part of #4858.
Follow-up from #4867 (the
pr-flowskill), which merged with its first acceptance criterion unmet: nothing fails a PR with an unsigned commit today. No DCO check ran on #4904, #4905 or #4906.The original plan was to install the probot DCO app, but the org appears to have turned it off. The Inspector hit the same thing (modelcontextprotocol/inspector#2566), where the app was suspended and its check quietly disappeared. As there, we replace the third-party app with a check we own.
Scope
Signed-off-by: Name <email>trailer whose name and email match the commit's author or committer. Keep the app's two exemptions: merge commits and bot-authored commits. One unsigned commit fails the job, and its output names the commit and thegit rebase --signoffrepair.typescript.ymlandpython.ymlrun on bothpushandpull_request, and a push job doesn't know the PR's base. A small separate workflow onpull_request(usinggithub.event.pull_request.base.sha..head.sha, orgh api …/pulls/N/commits --paginate) is cleaner than inferring a merge-base.contents: readonly, so the job holds no credential and stays outside the SHA-pin rule (verify:action-pins).timeout-minutes, asscripts/lib/workflow-gate.mjsrequires of every job.scripts/verify-dco.mjswith a siblingverify-dco.test.mjs, like the other guards.local:gate:stagesin the same change. Locally it can checkorigin/v2/main..HEAD, which also catches an unsigned commit before it is pushed.v2/mainand confirm the job fails. Then repair it withgit rebase --signoffand confirm it passes.v2/main. No ruleset applies tov2/maintoday, andmain's rulesets require no status checks, so this is a repo-admin settings change, not something the PR can do. Considermaintoo.AGENTS.md, which only states rules that are true of the repo today;.claude/skills/pr-flow/SKILL.mdstep 3 so it describes the new job instead of the probot app: delete the ".github/dco.yml/ remediation-commit / override-button discussion, which only applies to the app;AGENTS.mdskills-index table: theissue-triageandsecurity-advisoryrows were added without padding to avoid stacking conflicts.Acceptance criteria
local:gate:stages, and its script (if any) has unit tests.v2/main.AGENTS.mdstates the signoff rule, andpr-flowdescribes the job, not the app.Part of #4858.