Skip to content

Commit f1f9790

Browse files
wphillipmoorewphillipmoore-claude
andauthored
chore: sync tooling and add commit/PR wrapper script instructions (#326)
Co-authored-by: wphillipmoore-claude <255925739+wphillipmoore-claude@users.noreply.github.com>
1 parent 61c4139 commit f1f9790

7 files changed

Lines changed: 402 additions & 4 deletions

File tree

CLAUDE.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,39 @@ This approach ensures all AI agents (Codex, Claude, etc.) have access to the sam
324324
- `docs/repository-standards.md` - Project-specific standards (included from AGENTS.md)
325325
- `docs/standards-and-conventions.md` - Canonical standards reference (includes external repo)
326326

327+
## Commit and PR Scripts
328+
329+
**NEVER use raw `git commit`** — always use `scripts/dev/commit.sh`.
330+
**NEVER use raw `gh pr create`** — always use `scripts/dev/submit-pr.sh`.
331+
332+
### Committing
333+
334+
```bash
335+
scripts/dev/commit.sh --type feat --scope session --message "add retry logic" --agent claude
336+
scripts/dev/commit.sh --type fix --message "correct attribute mapping" --agent claude
337+
```
338+
339+
- `--type` (required): `feat|fix|docs|style|refactor|test|chore|ci|build`
340+
- `--message` (required): commit description
341+
- `--agent` (required): `claude` or `codex` — resolves the correct `Co-Authored-By` identity
342+
- `--scope` (optional): conventional commit scope
343+
- `--body` (optional): detailed commit body
344+
345+
### Submitting PRs
346+
347+
```bash
348+
scripts/dev/submit-pr.sh --issue 42 --summary "Add retry logic to session"
349+
scripts/dev/submit-pr.sh --issue 42 --linkage Ref --summary "Update docs" --docs-only
350+
```
351+
352+
- `--issue` (required): GitHub issue number (just the number)
353+
- `--summary` (required): one-line PR summary
354+
- `--linkage` (optional, default: `Fixes`): `Fixes|Closes|Resolves|Ref`
355+
- `--title` (optional): PR title (default: most recent commit subject)
356+
- `--notes` (optional): additional notes
357+
- `--docs-only` (optional): applies docs-only testing exception
358+
- `--dry-run` (optional): print generated PR without executing
359+
327360
## Key References
328361

329362
**Canonical Standards**: https://github.com/wphillipmoore/standards-and-conventions

docs/repository-standards.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,52 @@ Required for integration testing:
6767
- Feature PRs: `gh pr merge --auto --squash --delete-branch`
6868
- Release PRs: `gh pr merge --auto --merge --delete-branch`
6969

70+
## Commit and PR scripts
71+
72+
AI agents **must** use the wrapper scripts for commits and PR
73+
submission. Do not construct commit messages or PR bodies manually.
74+
75+
### Committing
76+
77+
```bash
78+
scripts/dev/commit.sh \
79+
--type TYPE --message MESSAGE --agent AGENT \
80+
[--scope SCOPE] [--body BODY]
81+
```
82+
83+
- `--type` (required): one of
84+
`feat|fix|docs|style|refactor|test|chore|ci|build`
85+
- `--message` (required): commit description
86+
- `--agent` (required): `claude` or `codex`
87+
- `--scope` (optional): conventional commit scope
88+
- `--body` (optional): detailed commit body
89+
90+
The script resolves the correct `Co-Authored-By` identity from the
91+
[AI co-authors](#ai-co-authors) section and the git hooks validate
92+
the result.
93+
94+
### Submitting PRs
95+
96+
```bash
97+
scripts/dev/submit-pr.sh \
98+
--issue NUMBER --summary TEXT \
99+
[--linkage KEYWORD] [--title TEXT] \
100+
[--notes TEXT] [--docs-only] [--dry-run]
101+
```
102+
103+
- `--issue` (required): GitHub issue number (just the number)
104+
- `--summary` (required): one-line PR summary
105+
- `--linkage` (optional, default: `Fixes`):
106+
`Fixes|Closes|Resolves|Ref`
107+
- `--title` (optional): PR title (default: most recent commit
108+
subject)
109+
- `--notes` (optional): additional notes
110+
- `--docs-only` (optional): applies docs-only testing exception
111+
- `--dry-run` (optional): print generated PR without executing
112+
113+
The script detects the target branch and merge strategy
114+
automatically.
115+
70116
## Temporary tooling workaround
71117

72118
- The Codex execution harness may reject `git branch -d` even with `sandbox_mode = "danger-full-access"`.

scripts/dev/commit.sh

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env bash
2+
# Commit wrapper that constructs standards-compliant commit messages.
3+
# Resolves Co-Authored-By identities from docs/repository-standards.md.
4+
5+
set -euo pipefail
6+
7+
repo_root="$(git rev-parse --show-toplevel)"
8+
9+
# --- Defaults ---
10+
type=""
11+
scope=""
12+
message=""
13+
body=""
14+
agent=""
15+
16+
# --- Argument parsing ---
17+
usage() {
18+
cat >&2 <<'EOF'
19+
Usage: scripts/dev/commit.sh --type TYPE --message MESSAGE --agent AGENT [options]
20+
21+
Required:
22+
--type TYPE Conventional commit type (feat|fix|docs|style|refactor|test|chore|ci|build)
23+
--message MESSAGE Commit description (text after "type: ")
24+
--agent AGENT AI tool identity: claude or codex
25+
26+
Optional:
27+
--scope SCOPE Conventional commit scope
28+
--body BODY Detailed commit body
29+
-h, --help Show this help
30+
EOF
31+
exit 1
32+
}
33+
34+
while [[ $# -gt 0 ]]; do
35+
case "$1" in
36+
--type) type="$2"; shift 2 ;;
37+
--scope) scope="$2"; shift 2 ;;
38+
--message) message="$2"; shift 2 ;;
39+
--body) body="$2"; shift 2 ;;
40+
--agent) agent="$2"; shift 2 ;;
41+
-h|--help) usage ;;
42+
*)
43+
echo "ERROR: unknown argument: $1" >&2
44+
usage
45+
;;
46+
esac
47+
done
48+
49+
# --- Validation ---
50+
51+
# Required arguments.
52+
if [[ -z "$type" ]]; then
53+
echo "ERROR: --type is required." >&2
54+
usage
55+
fi
56+
if [[ -z "$message" ]]; then
57+
echo "ERROR: --message is required." >&2
58+
usage
59+
fi
60+
if [[ -z "$agent" ]]; then
61+
echo "ERROR: --agent is required." >&2
62+
usage
63+
fi
64+
65+
# Validate type.
66+
allowed_types="feat|fix|docs|style|refactor|test|chore|ci|build"
67+
if [[ ! "$type" =~ ^(feat|fix|docs|style|refactor|test|chore|ci|build)$ ]]; then
68+
echo "ERROR: invalid --type '$type'. Allowed: $allowed_types" >&2
69+
exit 1
70+
fi
71+
72+
# Resolve agent identity from docs/repository-standards.md.
73+
profile_file="$repo_root/docs/repository-standards.md"
74+
if [[ ! -f "$profile_file" ]]; then
75+
echo "ERROR: repository profile not found at $profile_file" >&2
76+
exit 1
77+
fi
78+
79+
# Look for the identity whose username contains -<agent> (e.g., -claude, -codex).
80+
identity=""
81+
while IFS= read -r line; do
82+
# Lines look like: - Co-Authored-By: name <email>
83+
stripped="${line#- }"
84+
if echo "$stripped" | grep -qi "\-${agent}[[:space:]]"; then
85+
identity="$stripped"
86+
break
87+
fi
88+
done < <(grep -i '^\- Co-Authored-By:' "$profile_file" || true)
89+
90+
if [[ -z "$identity" ]]; then
91+
echo "ERROR: no approved identity found for agent '$agent' in $profile_file." >&2
92+
echo "Approved identities are listed under 'AI co-authors'." >&2
93+
exit 1
94+
fi
95+
96+
# Verify there are staged changes.
97+
if git diff --cached --quiet; then
98+
echo "ERROR: no staged changes. Stage files with 'git add' before committing." >&2
99+
exit 1
100+
fi
101+
102+
# --- Construct commit message ---
103+
subject="$type"
104+
if [[ -n "$scope" ]]; then
105+
subject="${subject}(${scope})"
106+
fi
107+
subject="${subject}: ${message}"
108+
109+
# Use a temporary file to preserve formatting (per AGENTS.md guidance).
110+
tmp_file="$(mktemp)"
111+
trap 'rm -f "$tmp_file"' EXIT
112+
113+
printf '%s\n' "$subject" > "$tmp_file"
114+
if [[ -n "$body" ]]; then
115+
printf '\n%s\n' "$body" >> "$tmp_file"
116+
fi
117+
printf '\n%s\n' "$identity" >> "$tmp_file"
118+
119+
# --- Commit ---
120+
git commit --file "$tmp_file"

0 commit comments

Comments
 (0)