FACTUAL ACTIVITY RECORD · An activity record based on work that took place
Standardizing the end state after a Pull Request merge
Adding a dirty-worktree guard and making local-main return, synchronization, and a clean check part of completion
Purpose
After a Pull Request was merged, the local repository could remain on the work branch without returning to main, retrieving the current remote state, or confirming a clean working tree. The CEO asked for completion to extend beyond the merge operation to a state from which the next task could start on the latest main.
This Activity defined the post-approval sequence as merging, checking related Issue state, returning to local main, fetching the remote, applying a fast-forward-only update, and confirming a clean state. It also implemented a repository-local wrapper that accepted no arguments and stopped on a dirty worktree so the sequence was harder to skip without risking uncommitted changes.
Implementation
At the start, local main appeared to match its cached tracking reference, but an actual remote read failed. Work began anyway, so after the CEO's correction that branch was excluded from the final basis. The uncommitted diff was temporarily set aside, the remote main was fetched, local main was fast-forwarded, and a new work branch was created before reapplying the diff. This brought the change itself back onto a base that satisfied the end-state rule being introduced.
scripts/return-to-main-after-merge implemented post-merge local cleanup as one ordered operation. It rejected any argument with exit code 2 and stopped with exit code 1 when git status --porcelain reported changes. Only a clean repository switched to main, fetched and pruned the remote, pulled with fast-forward-only semantics, and displayed the final branch and working-tree status.
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 0 ]; then
echo "usage: scripts/return-to-main-after-merge" >&2
exit 2
fi
if [ -n "$(git status --porcelain)" ]; then
echo "error: working tree is not clean; resolve local changes before returning to main" >&2
git status --short >&2
exit 1
fi
git switch main
git fetch --prune origin
git pull --ff-only origin main
git status --short --branchRendering diagram…
.codex/rules/organization.rules defined ordinary-cleanup entries for only the argument-free scripts/return-to-main-after-merge and ./scripts/return-to-main-after-merge forms. It did not grant a broad command-prefix allowance to git switch main or git pull --ff-only, and an argument-bearing wrapper invocation did not share those entries. Branch and option selection remained behind the wrapper's input boundary.
prefix_rule(
pattern = ["scripts/return-to-main-after-merge"],
decision = "allow",
match = [
"scripts/return-to-main-after-merge",
],
not_match = [
"git switch main",
"git pull --ff-only",
"scripts/return-to-main-after-merge feature-branch",
],
).agents/skills/software-delivery/SKILL.md updated the completion gate for software delivery. After CEO merge approval, the workflow completed the merge and related Issue check or closure, then required the wrapper to return local state to main, fetch, pull with fast-forward-only semantics, and confirm a clean state. The Skill's direct reference for drafting Issues and Pull Requests, .agents/skills/software-delivery/references/github-templates.md, was unchanged because this Activity altered post-approval sequencing and completion criteria rather than document templates.
The same boundary was applied in AGENTS.md and .codex/agents/full-stack-engineer.toml. The organization-wide rule required related-Issue handling and a return to the latest clean local main before completion reporting. The Full-Stack Engineer instructions added responsibility for using the wrapper without skipping steps after performing an approved merge and for reporting the result. This was a role-configuration change; it does not mean that a Full-Stack Engineer Custom Agent participated in the Activity.
Reader-facing operating guidance was synchronized across .codex/rules/README.md, docs/operating-model.md, and docs/setup.md. The sequence of merge approval, related-Issue handling, post-merge cleanup, and completion reporting became visible from configuration, the Skill, role instructions, and operating documentation. The final change covered eight files including the wrapper.
Verification checked the shell script syntax, parsed every Custom Agent TOML, and checked the diff for whitespace errors. Running the wrapper while the worktree contained the in-progress changes confirmed that it stopped before switching branches or reading the remote. After the change was incorporated, the wrapper was used immediately after an actual Pull Request merge, and local state returned to main, fast-forwarded to the remote's incorporated state, and ended with a clean working tree.
What was confirmed
Verification results
The post-merge completion criteria were aligned across configuration, the Skill, role instructions, and operating documentation as the merge, related-Issue check, return to local main, remote fetch, fast-forward update, and clean-state confirmation.
scripts/return-to-main-after-merge accepted no arguments and stopped before switching branches or updating local refs when the working tree was dirty. A clean repository proceeded through main, fetch --prune, pull --ff-only, and status output.
The command rules defined ordinary-cleanup entries for only the two argument-free wrapper forms and did not place direct switch, direct pull, or argument-bearing wrapper commands under those entries. This Activity did not execute a policy evaluator to test the resulting allow decision.
The shell syntax, Custom Agent TOML parsing, whitespace check, and dirty-worktree guard all completed with the expected results.
After the change was incorporated, the wrapper was used in an actual post-merge cleanup. Local state returned to main, fast-forwarded to the remote's incorporated state, and ended with a clean working tree.
The verified wrapper configuration was limited to a remote named origin and a branch named main. Alternate remotes, a different default branch, and recovery from network or authentication failure were not tested in this Activity. The clean check covered the working tree; it did not establish the absence of other local refs.
Basis for completion
The Activity was complete when the post-merge cleanup criteria were consistent across eight files, the wrapper syntax and dirty guard, TOML, and diff checks passed, and the same wrapper was then used to verify an actual return to local main, synchronization with the remote, and a clean working tree after incorporation.