aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-25 01:30:28 -0500
committerCraig Jennings <c@cjennings.net>2026-04-25 01:30:28 -0500
commit20de0eca58802bc778b5a0103c6b910762b447a4 (patch)
tree72ec020c5fd2bc105f7ccd29bd81b9c695bdfe82
parente5b54c24afdd569765b215732884bd0a8f2758a9 (diff)
downloadrulesets-20de0eca58802bc778b5a0103c6b910762b447a4.tar.gz
rulesets-20de0eca58802bc778b5a0103c6b910762b447a4.zip
docs(commits,testing): add merge strategy + multi-pass gate + time-mocking safety
commits.md gets two additions. A new "## Merge Strategy" section makes squash-merge the default for feature branches and requires explicit confirmation of the merge approach before pushing or merging. A new "Multi-pass gate" paragraph in Review and Publish requires every humanizer-flow pass to run and be named when declaring done, so silent skips become defects. testing.md gets a new bullet under "### Determinism": time/clock-mocking helpers must not recurse against the primitive they're mocking, and must not let-bind over a defvar — the binding shadows only inside the test scope, so production code reading the symbol still gets the original value (silent test miss).
-rw-r--r--claude-rules/commits.md24
-rw-r--r--claude-rules/testing.md7
2 files changed, 31 insertions, 0 deletions
diff --git a/claude-rules/commits.md b/claude-rules/commits.md
index 876677d..79f3b06 100644
--- a/claude-rules/commits.md
+++ b/claude-rules/commits.md
@@ -214,6 +214,15 @@ conversation (e.g. "commit this as `chore: bump version`", "reply just
`/review-code` in Step 1 still runs when it applies; Phase 0 of that skill
handles trivial diffs, and acknowledgment-only replies don't need it at all.
+**Multi-pass gate.** Each of the three subflows above lists a humanizer
+invocation followed by a sequence of additional passes (jargon rewrite,
+semicolon swap, contractions, sentence split). When the user asks for
+"both passes" or "all the passes" or just for the humanizer step, run
+*every* listed pass — not just the first or a representative subset.
+Before declaring done, name the passes you actually ran (e.g.
+"humanizer + jargon + semicolons + contractions + sentence-split — all
+applied"). Skipping a pass without flagging it is a defect.
+
### Hook-level authorization
The Step 1 code review plus the Step 2 user approval together constitute the
@@ -223,6 +232,21 @@ variants once Step 2 has been approved. If a hook is configured, rely on the
flow above to be the source of truth; do not treat the hook as a second
independent gate.
+## Merge Strategy
+
+- *Squash-merge is the default* for feature branches. It avoids carrying
+ WIP and fix-up commits into the target branch history and produces one
+ logical change per merge.
+- State the planned merge approach (squash, rebase, or merge commit) and
+ the target branch *before* pushing or merging. Wait for explicit user
+ confirmation before `git push`, `gh pr merge`, or any equivalent. The
+ Review and Publish flow above approves the *content*; merge strategy is
+ a separate decision that needs its own confirmation.
+- Override the squash default only when there's a concrete reason: a
+ clean per-commit review history the user has explicitly asked for, a
+ multi-commit semantic narrative the team values, etc. Squash is the
+ safe default; document why when deviating.
+
## Before Committing
1. Check author identity: `git log -1 --format='%an <%ae>'` — should be the user.
diff --git a/claude-rules/testing.md b/claude-rules/testing.md
index 02c6ce0..a6bc1df 100644
--- a/claude-rules/testing.md
+++ b/claude-rules/testing.md
@@ -158,6 +158,13 @@ the specific case choice.
- Never hardcode dates or times — generate them relative to `now()`
- No reliance on test execution order
- No flaky network calls in unit tests
+- Time/clock-mocking helpers must not call the primitives they're
+ mocking (infinite recursion), and must not `let`-bind over a
+ `defvar` or other globally-defined symbol (the binding shadows the
+ global only inside the test scope, so production code that reads the
+ symbol gets the original value, not the mock — silent test miss).
+ Mock by redefining at the symbol's definition site or via the
+ language's first-class mocking primitive.
### Performance
- Unit tests: <100ms each