Skip to content

Instantly share code, notes, and snippets.

@PaulSolt
Last active January 17, 2026 06:07
Show Gist options
  • Select an option

  • Save PaulSolt/5c1ac1d9220eb67744ea70ec9810336d to your computer and use it in GitHub Desktop.

Select an option

Save PaulSolt/5c1ac1d9220eb67744ea70ec9810336d to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Atomic commit helper to prevent AI's from accidentally deleting
# changes from dangerous commands. I only allow AI agents to commit with this flow.
# I disallow AI agents from git reset, git checkout, and git revert because
# they are dangerous operations when multiple agents (or I) are editing
# files in the same work tree.
set -euo pipefail
usage() {
cat >&2 <<'EOF'
Usage: scripts/atomic_commit.sh "commit message" <path> [<path> ...]
Runs the approved sequence:
git reset
git add -- <paths>
git commit -m "commit message" -- <paths>
EOF
}
if [[ $# -lt 2 ]]; then
usage
exit 1
fi
commit_message=$1
shift
if [[ -z "${commit_message// }" ]]; then
echo "Error: commit message must not be empty." >&2
exit 1
fi
repo_root=$(git rev-parse --show-toplevel 2>/dev/null) || {
echo "Error: scripts/atomic_commit.sh must be run inside a Git repository." >&2
exit 1
}
cd "$repo_root"
files=("$@")
missing=()
pristine=()
for path in "${files[@]}"; do
if [[ ! -e "$path" ]]; then
if ! git ls-files --error-unmatch -- "$path" >/dev/null 2>&1; then
missing+=("$path")
continue
fi
fi
status_output=$(git status --short -- "$path")
if [[ -z "$status_output" ]]; then
pristine+=("$path")
fi
done
if [[ ${#missing[@]} -gt 0 ]]; then
printf 'Error: the following paths do not exist or are not tracked:\n' >&2
printf ' %s\n' "${missing[@]}" >&2
exit 1
fi
if [[ ${#pristine[@]} -gt 0 ]]; then
printf 'Error: no changes detected for:\n' >&2
printf ' %s\n' "${pristine[@]}" >&2
exit 1
fi
git reset
git add -- "${files[@]}"
git commit -m "$commit_message" -- "${files[@]}"
## Agents Exerpt around Git Best Practices
## Tasks
- **Git workflow (non-negotiable):** Every subtask listed in `docs/TASKS.md` must be a self-contained commit. Follow this loop for *each* subtask:
1. Pick a task/subtask from `docs/TASKS.md` and confirm the plan.
2. Start the subtask (update the Task Breakdown if needed) and edit only what the subtask requires.
3. Do the work + keep the app/build green at all intermediate points.
4. Verify locally (`make …` tests, Peekaboo evidence, etc.) and note logs/artifacts.
5. Run `scripts/atomic_commit.sh "Agent <NAME>: intent" <files…>` immediately—no batching with the next subtask.
Repeat for the next subtask until the feature is finished. If a feature spans phases, each phase is still composed of granular subtasks, and each subtask lands as its own atomic commit before moving on. Large “catch‑all” commits are never acceptable because they block Paul and other agents from testing in the middle of your work.
- **Pending-decision workflow.** If a question only blocks one subtask, do not halt the entire task. Spell out the question in chat, continue with every other subtask that remains valid, and stub the blocked area with a TODO comment formatted as `// TODO(Agent <Name>, <TaskID>): Pending Paul decision — <context>`. Paul’s “continue” instruction means “finish every unblocked subtask, leave the TODO in place, and circle back once an explicit answer arrives.” Remove the TODO as soon as the decision is resolved so other agents are never stuck on your placeholder.
- **Subtask continuation discipline.** Use the word “subtask” everywhere (never “slice”). When one subtask is blocked but others are free, explicitly table the blocked item, keep shipping the remaining subtasks, and restate the open question at every check-in so Paul can respond without digging through history. Annotate the code with `// TODO(Agent <Name>, <TaskID>): Pending Paul decision — …` plus a matching note in `docs/TASKS.md`, then resume work once Paul answers.
- **“Continue” rule.** When Paul says “continue,” it only means “keep working until the current task (all subtasks) is finished.” It never counts as approval for a proposed decision or fallback. If you were blocked on a question and still lack an explicit answer, repeat the question until Paul provides one—even if he says “continue” in between. While you wait, mention which subtask remains blocked so other agents understand the dependency.
## Git Rules
- ABSOLUTELY NEVER run destructive git operations (e.g., `git reset --hard`, `rm`, `git checkout`/`git restore` to an older commit) unless the user gives an explicit, written instruction in this conversation. Treat these commands as catastrophic; if you are even slightly unsure, stop and ask before touching them. *(When working within Cursor or Codex Web, these git limitations do not apply; use the tooling's capabilities as needed.)*
- "No destructive actions" Always ask before removing files or items from git. Unless you have my explicit approval and direction.
- Never use `git restore` (or similar commands) to revert files you didn't author—coordinate with other agents instead so their in-progress work stays intact.
- Always double-check git status before any commit
- Allowed git commands: **only** `git status`, `git diff <path>`, and `git log`. All other git subcommands are forbidden unless Paul gives written approval in this chat. The atomic commit helper runs the necessary plumbing (`git reset`, `git add`) on your behalf—never invoke those directly.
- Keep commits atomic: use `scripts/atomic_commit.sh "Agent <NAME>: <intent>" <file1> <file2> ...` for every commit. The helper performs the approved `git reset`, `git add -- <paths>`, and `git commit -- <paths>` sequence so you never stage files you didn’t touch. Never invoke `git add`, `git commit`, `git reset`, or related commands directly.
- Quote any git paths containing brackets or parentheses (e.g., `src/app/[candidate]/**`) when staging or committing so the shell does not treat them as globs or subshells.
- Never amend commits unless you have explicit written approval in the task thread.

Numbering rule: Task IDs use plain integers (no leading zeros).

Task schema + ownership rules live in AGENTS.md (see Task Tracking Schema). Use the ID prefixes below whenever you add new items; legacy sections will migrate to the new format as we groom them. Task IDs never include leading zeros (e.g., AD-12). Only check a phase or parent task after the underlying code/tests/docs have merged; if anything is still outstanding, leave the checkbox unchecked and call out the remaining work in the notes. When you pause or hand off work, follow these handoff rules:

  1. Capture the latest xcodebuild log exactly as described in docs/apple/xcodebuild.md (for example, make ara-build | tee build_build.log).
  2. Record the log’s path/name in the task notes so the next agent can pick up without rerunning blind.

Formatting / ordering rules: • Prepend every task entry with a Markdown header ## AD-XX — Title so IDs are easy to scan. • Keep tasks sorted by ID; when adding a new entry, insert it in numeric order and update the ledger. • Before minting an ID, run rg -- 'AD-XX' docs/TASKS.md (replacing XX) to ensure the identifier is unused.

Pipeline / ROI work: Before editing those areas, follow the guardrails in docs/AI-Onboarding.md (ROI section) and docs/TestingPlaybook.md §10. Task notes must list the docs you re-read, the ROI/Peekaboo evidence you captured, and confirm that code changes include // Agent: Required reading ... comments referencing the relevant blueprint sections.

Task ID Ledger

Update these counters whenever you mint a new task ID so numbering continues to increase per project.

Prefix Project / Area Next ID
IQ ImageQuality persistence & docs 1
AD ArachnidDetector 13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment