diff --git a/data/AGENTS.md b/data/AGENTS.md index 80200d4..53c1652 100644 --- a/data/AGENTS.md +++ b/data/AGENTS.md @@ -1,5 +1,11 @@ # Agents +Operating rules for every agent in this registry. Full procedures live in the `committing-changes` and `using-worktrees` skills. + +**Committing** — Commit only on Sam's explicit command, never autonomously and never on apply; never `git push` (Sam pushes manually, Gitea + GitHub mirror). Stage by concern (named files or `git add -p`), never `git add -A`; never stage Sam's unrelated work. Identity `indifferentketchup` / `sam@indifferentketchup.com`, never a personal Gmail. Freeform scope-prefix messages, explain *why* for non-obvious changes, no emojis. Full workflow: invoke `committing-changes`. + +**Worktrees** — Isolate work in a worktree when it is parallel to in-progress work, risky/experimental, a hotfix interrupting other work, or splits into independent units — just create when clear, propose in one line when ambiguous, skip quick/small single-stream work. Branch from a stable base (default branch); worktrees persist (never auto-remove or auto-merge); they isolate code state, not runtime (ports/DBs/services still collide). Full heuristic: invoke `using-worktrees`. + ## Code Reviewer --- temperature: 0.6 diff --git a/data/skills/boocode/committing-changes/SKILL.md b/data/skills/boocode/committing-changes/SKILL.md new file mode 100644 index 0000000..49d7afa --- /dev/null +++ b/data/skills/boocode/committing-changes/SKILL.md @@ -0,0 +1,60 @@ +--- +name: committing-changes +description: This skill should be used when the user asks to commit, stage, split, or prepare changes for a commit. Examples: "commit this", "stage these", "split this into commits", "help me commit", "prepare a commit", "make a commit for the dcp fix". +--- + +# Committing Changes + +Segment the working tree by concern, stage explicitly, draft messages, **present the plan, and STOP**. Commit only on the user's explicit command for this turn. Never push — the user pushes manually (Gitea + GitHub mirror). + +**The default is to prepare and propose, not to commit.** A request to "commit X" is a request to get X *ready* and show the plan, unless the user has, in this turn, told you to actually run the commit. When in doubt, present and wait. + +## Workflow + +1. **Inspect.** `git status` then `git diff` (and `git diff --staged` if anything is already staged). Read what actually changed — do not commit from memory of what you wrote. +2. **Segment by concern.** Group the changes into buckets, one per coherent concern. State the grouping in plain language before staging anything (e.g. "two concerns: (a) the SSE fix in opencode-server.ts, (b) an unrelated typo in README"). +3. **Safety scan.** Before staging, scan the diff for: secrets / keys / tokens, debug code, stray `console.log`/`print`/`dbg!`, commented-out experiments, and edits to files the user did not ask you to touch (their in-progress work). Flag anything found; do not silently stage it. +4. **Stage explicitly, per bucket.** Stage named files (`git add path/a path/b`) or hunks (`git add -p`). **Never `git add -A`, `git add .`, or `git add -u`** — those sweep up unrelated work. If `-p` can't cleanly split adjacent hunks, hand-edit the patch (`git add -e`) or revert the unrelated hunk in the working tree first. +5. **Draft messages.** One message per bucket, in the repo's scope-prefix style (see `references/message-style.md`). Explain *why* for anything non-obvious — the diff already shows *what*. Imperative mood. No emojis. Do not impose Conventional-Commits ceremony (type enums, `BREAKING CHANGE:` footers) unless the user asks. +6. **Present the plan + STOP.** Show: the buckets, the files in each, the drafted message for each, and the current staged state. Then wait. **Do not run `git commit`.** +7. **On the user's command**, execute the agreed `git add` / `git commit` exactly as presented, using the identity below. Then report the resulting hashes. Still do not push. + +## Split heuristic + +- **One commit** when the changes are a single coherent concern (a feature + its test; a fix + the comment explaining it). +- **Multiple commits** when concerns are independently revertable or reviewable — a bug fix and an unrelated refactor that happen to share the working tree should be two commits even if they touch the same file. +- A migration/schema change and the code that uses it are usually *one* concern (they're not independently revertable). A doc/changelog update alongside code is usually a *separate* concern. + +## Identity (always) + +Commit as: + +``` +user.name = indifferentketchup +user.email = sam@indifferentketchup.com +``` + +Never use a personal Gmail or the host's default git identity. If unsure the repo config is right, pass it inline: `git -c user.name=indifferentketchup -c user.email=sam@indifferentketchup.com commit -m "..."`. + +## DO-NOT + +- **Never push.** No `git push` under any circumstances — that is the user's manual step (dual remote: Gitea + GitHub mirror). +- **Never auto-commit.** Preparing ≠ committing. Commit only when told to, this turn. +- **Never `git add -A` / `git add .` / `git add -u`.** Stage by name or by hunk. +- **Never commit the user's unrelated/in-progress files.** If a file changed that the task didn't touch, leave it; surface it. +- **No emojis** in messages. +- **No amending or rebasing** published or shared commits without an explicit instruction. + +## Red flags — STOP + +- About to run `git commit` without having been told to commit this turn → STOP, present the plan instead. +- About to `git add -A` "to save time" → STOP, stage by concern. +- About to `git push` "to finish the job" → STOP, that is never part of this skill. +- A secret or debug line is in the diff and you're staging anyway → STOP, surface it. + +## Anti-patterns this skill avoids + +- Committing the moment changes look done (the user reviews diffs and commits on command). +- Collapsing several concerns into one "WIP" commit because staging separately is tedious. +- Pushing after committing because the work "feels finished." +- Reformatting the message into strict Conventional Commits when the repo uses freeform scope-prefixes. diff --git a/data/skills/boocode/committing-changes/eval.yaml b/data/skills/boocode/committing-changes/eval.yaml new file mode 100644 index 0000000..fa310a7 --- /dev/null +++ b/data/skills/boocode/committing-changes/eval.yaml @@ -0,0 +1,31 @@ +skill: committing-changes +tasks: + - prompt: "Commit this for me" + grader: + - the response invokes the committing-changes skill + - the response inspects the working tree (git status / git diff) before staging + - the response segments the changes by concern and states the grouping + - the response stages explicitly (named files or git add -p), never git add -A / git add . / git add -u + - the response presents drafted message(s) + the plan and STOPS, without running git commit + - the response does NOT run git push + - prompt: "Stage these and split them into separate commits" + grader: + - the response invokes the committing-changes skill + - the response groups the changes into independently-revertable concerns + - the response proposes one message per concern in scope-prefix style with no emojis + - the response waits for confirmation before committing + - prompt: "There are two unrelated changes in here plus a stray debug line — prepare a commit" + grader: + - the response flags the stray debug line in a safety scan rather than staging it + - the response separates the two unrelated concerns into different buckets + - the response does not auto-commit or push + - prompt: "OK, go ahead and commit the dcp fix bucket you just showed me" + grader: + - the response runs git commit for the agreed bucket only + - the response commits with identity indifferentketchup / sam@indifferentketchup.com + - the response does NOT run git push afterward + - the response reports the resulting commit hash + - prompt: "Explain how git's three-way merge works" + grader: + - the response does NOT invoke the committing-changes skill + - the response answers the conceptual question directly diff --git a/data/skills/boocode/committing-changes/references/message-style.md b/data/skills/boocode/committing-changes/references/message-style.md new file mode 100644 index 0000000..96bd89c --- /dev/null +++ b/data/skills/boocode/committing-changes/references/message-style.md @@ -0,0 +1,43 @@ +# Commit message style + +Freeform **scope-prefix** messages. The shape is conventional-commits-*like* — `type(scope): summary` is the dominant form in this repo — but it is **not enforced**: the scope and the *why* matter more than the type enum. Do not reject or rewrite a message just because it lacks a `type`, and do not add ceremony (`BREAKING CHANGE:` footers, rigid type whitelist). + +## The pattern + +``` +: + + +``` + +- **Scope prefix** — the area(s) touched. A single area (`coder`, `web`, `server`), a typed scope (`fix(coder)`, `feat(coder)`, `docs(changelog)`), a sub-scope (`coder(providers)`), or multiple areas joined (`web+coder`). Pick whatever names the blast radius honestly. +- **Imperative summary** — "strip dcp tags", not "stripped" / "strips". One line, no trailing period needed. +- **Body** — only when the *why* isn't obvious from the summary. Explain the reason, the failure it fixes, or the constraint it satisfies. Cross-reference related tags/commits by name when the change builds on or fixes prior work. +- **No emojis.** Anywhere — summary, body, or trailers. + +## Real examples (from this repo's log) + +``` +fix(coder): strip dcp-message-id tags split across stream chunks +feat(coder): per-session SSE subscriptions (P1.5-a concurrency prereq) +feat(coder): guard session delete against worktree work loss +fix(coder): no-upstream branch alone no longer flags a session at-risk +docs(changelog): v2.6.2-delete-guard-and-sse +chore(coder): untrack live coder-providers.json, ship example +``` + +And the freeform multi-area / sub-scope forms the house style also allows: + +``` +web+coder: per-session SSE +coder(providers): fix empty picker +``` + +## Why-not-just-what + +A summary that restates the diff (`fix: change variable name`) wastes the message. A good message answers a question the diff can't: *why did this need to change?* Example — the bare summary `fix(coder): no-upstream branch alone no longer flags a session at-risk` is fine, but its body earns its keep: + +> Session worktree branches never get an upstream, so the original rule flagged +> every worktree-backed session as at-risk on delete — even pristine ones. + +That sentence is the part a future reader (or `git blame`) actually needs. diff --git a/data/skills/boocode/using-worktrees/SKILL.md b/data/skills/boocode/using-worktrees/SKILL.md new file mode 100644 index 0000000..93635c2 --- /dev/null +++ b/data/skills/boocode/using-worktrees/SKILL.md @@ -0,0 +1,73 @@ +--- +name: using-worktrees +description: This skill should be used when starting work that may need isolation from the current checkout — parallel to something already in progress, risky or experimental, a hotfix interrupting other work, or a task that splits into independent mergeable units. Also when the user explicitly asks for a worktree. Examples: "try this risky refactor", "I need to fix prod while keeping this branch", "explore an alternate approach", "make a worktree for X". +--- + +# Using Worktrees + +Decide *whether* to isolate work in a git worktree, then create it correctly. The judgment — "does this need its own worktree?" — is the point of this skill; the mechanics are routine. + +**Asymmetry with committing (deliberate):** when the heuristic clearly fires, **just create the worktree** — you have standing trust here. When it's ambiguous, **propose it in one line and wait**. This is unlike committing, which is always command-gated. Creating a worktree is cheap and reversible; making a commit is not, so the trust differs. + +## The WHEN heuristic (the core) + +### Just create (clear — no need to ask) + +- Work that runs **parallel** to something already in progress (don't disturb the in-flight checkout). +- A **risky / experimental / throwaway** change you might want to discard cleanly. +- A **hotfix that interrupts** in-progress work (isolate the fix, leave the WIP untouched). +- Work that **decomposes into independent mergeable units** — one worktree per unit. +- Any task where the user would plausibly want it isolated from the main checkout. + +### Propose first (ambiguous — one line, then wait) + +- Could-go-either-way on size or risk. +- Unsure whether the user wants isolation at all. +- A worktree that would **overlap heavily** with the work already on the main checkout (isolation buys little, may confuse). + +State it in one line: *"This looks risky/parallel — want me to do it in a worktree?"* Then wait. + +### Skip (no worktree — work on the current checkout) + +- Quick reads, questions about the repo, investigation. +- Small single-stream fixes with nothing to run in parallel. +- Anything where there's nothing to isolate and no parallelism to protect. + +``` +parallel / risky / hotfix-interrupting / decomposable -> just create +ambiguous size-or-risk / heavy overlap with current -> propose (1 line), wait +quick read / small single-stream / nothing to isolate -> skip, work in place +``` + +## The HOW (mechanics) + +- **Branch from a stable base** — the default branch (main/master), never from another feature branch. A worktree off a half-done branch inherits its instability. +- **Branch name derived from the task** — `fix-session-delete-guard`, not `wip` or `tmp`. No emojis. +- **Collision-safe path** — a unique dir outside the main checkout (e.g. a per-task or per-branch path), so two worktrees never share a directory. +- **Run the project's setup after create** — install deps / env / generate, if the project defines a setup step. A fresh worktree has the code but not the installed/generated state. (Some projects declare setup hooks; run whatever the project defines — don't assume the checkout is ready to run bare.) + +## Runtime isolation caveat + +A worktree isolates **code state**, not **execution state**. Ports, databases, caches, lockfiles, and running services can still collide between worktrees. Don't assume a worktree means a fully isolated environment — if two worktrees both run the app, give each its own port / DB / service via per-worktree setup. Code isolation ≠ runtime isolation. + +## Lifecycle + +- Worktrees **persist** — they are not auto-reaped. Leaving one around is fine; it's not litter. +- **Reconcile via git**, never automatically: review the worktree's diff against its base, then merge or archive on the user's decision. Do not auto-merge. +- **Commit inside a worktree only on the user's command** — defer to the `committing-changes` skill for the commit step (same rules: present-and-stop, never push). + +## DO-NOT + +- **Never branch from a non-stable base** (another feature branch). Stable base only. +- **Never auto-merge or auto-reconcile** a worktree back. That's a reviewed decision. +- **Never push** (worktrees change nothing about the push rule — that stays the user's manual step). +- **Never `git worktree remove`** without the user's say. Worktrees persist; removing one can discard uncommitted work. +- **No emojis** in branch names. + +## Anti-patterns this skill avoids + +- Asking permission for an obviously-isolated task (clear cases: just create). +- Creating a worktree for a quick read or a one-line fix (nothing to isolate). +- Branching the worktree off the messy in-progress branch instead of the stable base. +- Assuming a worktree gives runtime isolation and then colliding on a port or DB. +- Auto-removing or auto-merging a worktree the user hasn't reconciled. diff --git a/data/skills/boocode/using-worktrees/eval.yaml b/data/skills/boocode/using-worktrees/eval.yaml new file mode 100644 index 0000000..b6ef9ad --- /dev/null +++ b/data/skills/boocode/using-worktrees/eval.yaml @@ -0,0 +1,32 @@ +skill: using-worktrees +tasks: + - prompt: "I'm mid-way through a feature but prod is broken — I need to fix it now" + grader: + - the response invokes the using-worktrees skill + - the response recognizes this as a clear case (hotfix interrupting in-progress work) and just creates the worktree rather than asking + - the response branches the worktree from the stable/default branch, not the in-progress feature branch + - the response does NOT push + - prompt: "Let's try a risky refactor of the inference loop and see if it pans out" + grader: + - the response invokes the using-worktrees skill + - the response treats this as a clear case (risky/experimental) and creates a worktree autonomously + - the response uses a task-derived branch name (no emojis) and a collision-safe path + - the response notes that project setup must run in the new worktree before it can run + - prompt: "Should I do this small one-line typo fix in a worktree?" + grader: + - the response invokes the using-worktrees skill + - the response recommends SKIP (small single-stream fix, nothing to isolate) and works in place + - the response does not create a worktree + - prompt: "This change is medium-sized and I'm not sure if it'll conflict with what I'm doing" + grader: + - the response invokes the using-worktrees skill + - the response treats this as ambiguous and PROPOSES a worktree in one line, then waits, rather than creating it unilaterally + - prompt: "Two coder worktrees both run the app on port 9502 — will they be isolated?" + grader: + - the response invokes the using-worktrees skill + - the response explains that worktrees isolate code state but NOT runtime (ports/DBs/services can still collide) + - the response recommends per-worktree setup to separate the runtime + - prompt: "What's the difference between git clone and git worktree?" + grader: + - the response does NOT invoke the using-worktrees skill + - the response answers the conceptual question directly