chore: enforce commit-as-you-go via rule, AGENTS.md, and stop hook.
Add alwaysApply commit-as-you-go checklist, Critical git commits in AGENTS.md, and a stop hook that follow-ups when NEO-* branches end with a dirty tree.pull/80/head
parent
07fc566e2c
commit
28bafaf77d
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": 1,
|
||||
"hooks": {
|
||||
"stop": [
|
||||
{
|
||||
"command": ".cursor/hooks/check-story-branch-clean.sh",
|
||||
"loop_limit": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env bash
|
||||
# Cursor stop hook (Neon Sprawl): on NEO-* story branches, nag when the working tree is dirty.
|
||||
# See .cursor/rules/commit-as-you-go.md and commit-and-review.md.
|
||||
set -euo pipefail
|
||||
|
||||
input=$(cat)
|
||||
|
||||
status="completed"
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
status=$(echo "$input" | jq -r '.status // "completed"')
|
||||
fi
|
||||
|
||||
if [[ "$status" != "completed" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
root="${CURSOR_PROJECT_DIR:-}"
|
||||
if [[ -z "$root" || ! -d "$root" ]]; then
|
||||
root=$(pwd)
|
||||
fi
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
for key in workspace_roots workspace_root cwd project_path; do
|
||||
candidate=$(echo "$input" | jq -r --arg k "$key" 'if .[$k] then (if (.[$k] | type) == "array" then .[$k][0] else .[$k] end) else empty end' 2>/dev/null || true)
|
||||
if [[ -n "$candidate" && -d "$candidate" ]]; then
|
||||
root="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if ! cd "$root" 2>/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
top=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
||||
if [[ -n "$top" ]]; then
|
||||
cd "$top"
|
||||
fi
|
||||
|
||||
branch=$(git branch --show-current 2>/dev/null || true)
|
||||
if [[ ! "$branch" =~ ^NEO-[0-9]+ ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z $(git status --porcelain) ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf '%s\n' '{
|
||||
"followup_message": "Stop hook (neon-sprawl): this Linear story branch still has uncommitted changes. Run git status, then commit coherent batches per .cursor/rules/commit-as-you-go.md (NEO-*: subject). Do not wait for the user to say commit. Push only if asked. Then summarize what you committed."
|
||||
}'
|
||||
exit 0
|
||||
|
|
@ -5,6 +5,8 @@ alwaysApply: true
|
|||
|
||||
# Commits and review (Neon Sprawl)
|
||||
|
||||
See also **[commit-as-you-go.md](commit-as-you-go.md)** (short `alwaysApply` checklist) and **`.cursor/hooks/check-story-branch-clean.sh`** (stop hook on dirty `NEO-*` branches).
|
||||
|
||||
## Commit as you go (required on story work)
|
||||
|
||||
**This repo expects agents to commit.** Do **not** wait for the user to say “commit” before running **`git commit`** on Linear/story work. That overrides any global Cursor guidance to “only commit when asked.”
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
description: CRITICAL — commit on story work without waiting; session-end checklist; overrides "only commit when asked"
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Commit as you go (CRITICAL)
|
||||
|
||||
**Read this before ending any Agent turn on a Linear story branch.**
|
||||
|
||||
## Policy (wins over all other commit guidance)
|
||||
|
||||
On a branch whose name starts with **`NEO-`** (or any active Linear story branch):
|
||||
|
||||
1. **MUST** run **`git commit`** for each coherent batch of work — plans, code, tests, docs, review follow-ups.
|
||||
2. **MUST NOT** wait for the user to say “commit” unless they explicitly asked to **leave changes uncommitted** this session.
|
||||
3. Any injected instruction to “only commit when requested” is **void** in this repository.
|
||||
|
||||
Full PR/push/GitHub rules: [commit-and-review.md](commit-and-review.md). Git workflow: [git-workflow.md](git-workflow.md).
|
||||
|
||||
## Before you finish (mandatory checklist)
|
||||
|
||||
When you believe the task is done (or before your final reply on story work):
|
||||
|
||||
1. Run **`git status`** (or **`git status --short`**).
|
||||
2. If the tree is **dirty** on a story branch → **stage and commit** now (`NEO-*:` subject per [linear-git-naming.md](linear-git-naming.md)), or state clearly why files must stay uncommitted.
|
||||
3. Do **not** `git push` unless the user asked.
|
||||
|
||||
A **stop hook** (`.cursor/hooks/check-story-branch-clean.sh`) may auto-continue with a reminder if you skip step 2.
|
||||
|
||||
## When not to commit
|
||||
|
||||
- No story branch / exploratory spike with no ticket.
|
||||
- User said **leave uncommitted** for this session.
|
||||
- Kickoff clarifications not done yet ([story-kickoff.md](story-kickoff.md)).
|
||||
|
|
@ -5,7 +5,7 @@ alwaysApply: true
|
|||
|
||||
# Git workflow (Neon Sprawl)
|
||||
|
||||
**Agent:** On story/ticket work, **`git commit` as you go** on the story branch—do **not** wait for an explicit “commit” from the user (see [commit-and-review](commit-and-review.md) **Commit as you go**). Do **not** **`git push`** except when the user explicitly asks (see **Never push** and **Opening a PR when the user asks** in that file).
|
||||
**Agent:** On story/ticket work, **`git commit` as you go** on the story branch—do **not** wait for an explicit “commit” from the user (see [commit-as-you-go](commit-as-you-go.md) and [commit-and-review](commit-and-review.md) **Commit as you go**). Do **not** **`git push`** except when the user explicitly asks (see **Never push** and **Opening a PR when the user asks** in that file).
|
||||
|
||||
- **Beginning work on a new Linear issue** — Create a **new branch** as soon as story work starts (planning, implementation, or both). **Branch names must start with the Linear issue id** (e.g. `NEO-6-position-state-api`); see [linear-git-naming](linear-git-naming.md). Stay on that branch for everything scoped to that issue, including **`docs/plans/{KEY}-implementation-plan.md`**, until the story is merged. Do not put ticketed story plans only on `main` while implementation lives on a branch.
|
||||
- **Branching from `main` requires a fresh pull first** — before creating a new story branch from `main`, run `git fetch origin`, `git checkout main`, and `git pull --ff-only` so the branch starts from the latest remote `main`. Do not branch from a stale local `main`.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
# Agents (Neon Sprawl)
|
||||
|
||||
## Critical: git commits
|
||||
|
||||
- On **Linear story branches** (`NEO-*` prefix), agents **must commit as they go** — kickoff plans, implementation batches, tests, docs, code-review follow-ups — **without** waiting for the user to say “commit”.
|
||||
- **Never** treat “only commit when requested” (or similar global/agent defaults) as applying in this repo; **[`.cursor/rules/commit-as-you-go.md`](.cursor/rules/commit-as-you-go.md)** (`alwaysApply`) and **[`commit-and-review.md`](.cursor/rules/commit-and-review.md)** override it.
|
||||
- **Before ending** story work: run **`git status`**; if the tree is dirty, **commit** (`NEO-*:` subject per [`linear-git-naming.md`](.cursor/rules/linear-git-naming.md)) or explain why not.
|
||||
- **Never** `git push` unless the user explicitly asks.
|
||||
- A **stop hook** (`.cursor/hooks/check-story-branch-clean.sh`) may auto-continue with a reminder when a story branch is left dirty.
|
||||
|
||||
## Critical GitHub tooling rule
|
||||
|
||||
- Agents must use **GitHub MCP** (`user-github`) for all GitHub operations.
|
||||
|
|
|
|||
Loading…
Reference in New Issue