Skip to content

Judge a WIP commit before and after it separately (0.13.3) - #31

Merged
dsnger merged 2 commits into
mainfrom
fix-wip-message-pre-post
Sep 29, 2026
Merged

dsnger merged 2 commits into
mainfrom
fix-wip-message-pre-post

Conversation

@dsnger

@dsnger dsnger commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

The hook decided a -m "wip…" commit with one check used twice: the WIP note before the
commit and the kept counters after it. So a repository hook that rewrote the message into a
real one, or a chain such as git commit -m "real" && git commit -m "WIP", still kept the
Gate-B cycle. The two decisions are now separate.

Before: only an allow-listed one-line form counts - git commit, then only -a/--all,
-q/--quiet, -n/--no-verify, --amend or --allow-empty, and exactly one -m whose quoted or bare
value starts with wip; no editor, --fixup, -F, second -m, chain, cd, git -C, shell
metacharacter or backslash. Where a hook or setting could rewrite the message, the ordinary
Gate-B reminder is shown instead of the WIP note (a reminder, not a reset).

After: the counters stay only if the resulting commit starts with wip and is attributable to
the command. PreToolUse records HEAD, its parent, the HEAD reflog length and whether --amend
is an option in .context/codex-gate.wipBase; afterwards HEAD and the reflog are unchanged
(the commit failed), or the reflog grew by exactly one and HEAD sits on the recorded HEAD, or
on its parent for --amend. A hook that commits, amends or resets in between, a missing or
corrupt record, an empty HEAD reflog, or a Bash call sent to the background resets. The
0.13.2 --amend --no-edit rules are unchanged.

CLAUDE.md §5 Mechanics and its workflow-init copy (identical) now recommend
git commit -m 'WIP: …', state what else is accepted and the after-commit condition;
docs/architecture.md and docs/getting-started.md point to those rules. The WIP note no longer
promises the counters are kept. Tests run real commits between PreToolUse and PostToolUse
under sh and dash for every row: plain, harmless hook, rewriting hook, failed commit, chains,
extra -m/-F/--fixup/-e, hook-made extra commits, amend-back, --amend inside the message, no
reflog, corrupt record, background call; each repair's new cases fail on the previous hook.
dev-workflow 0.13.2 -> 0.13.3.

Gate B: six logical passes, each two sequential calls (spec, then quality) against the same
base and head ids; closed on pass 6 with no findings. A small persistent record was added by
the user's decision after pass 2. Pass reports: one tell at pass 3 (finding count rose,
5 -> 9), none reaching the two-tell stop. No story cited, so no evidence entry is owed.

cycle hpg0kyk2nz; floor 3 per none; hook reminder threshold absent
cycle hpg0kyk2nz; Gate B (passes 1-6, codex): Findings 6,5,9,7,1,0. Blockers 0,0,0,0,0,0. Majors 3,2,4,4,1,0.

Human exceptions: none

Summary by CodeRabbit

  • Bug Fixes

    • Improved WIP commit handling so a review cycle stays open only when the commit can be confirmed as qualifying. Other detected commits, uncertain outcomes, and backgrounded commits reset the cycle counters.
    • Updated the reminder shown when repository settings or hooks could change a WIP commit message.
  • Documentation

    • Clarified which WIP commit forms can keep a review cycle open, how commits are verified, and when counters reset.
    • Updated the getting-started guidance and workflow documentation to reflect these conditions.

The hook decided a `-m "wip…"` commit with one check used twice: the WIP note before the
commit and the kept counters after it. So a repository hook that rewrote the message into a
real one, or a chain such as `git commit -m "real" && git commit -m "WIP"`, still kept the
Gate-B cycle. The two decisions are now separate.

Before: only an allow-listed one-line form counts - `git commit`, then only -a/--all,
-q/--quiet, -n/--no-verify, --amend or --allow-empty, and exactly one -m whose quoted or bare
value starts with wip; no editor, --fixup, -F, second -m, chain, cd, git -C, shell
metacharacter or backslash. Where a hook or setting could rewrite the message, the ordinary
Gate-B reminder is shown instead of the WIP note (a reminder, not a reset).

After: the counters stay only if the resulting commit starts with wip and is attributable to
the command. PreToolUse records HEAD, its parent, the HEAD reflog length and whether --amend
is an option in .context/codex-gate.wipBase; afterwards HEAD and the reflog are unchanged
(the commit failed), or the reflog grew by exactly one and HEAD sits on the recorded HEAD, or
on its parent for --amend. A hook that commits, amends or resets in between, a missing or
corrupt record, an empty HEAD reflog, or a Bash call sent to the background resets. The
0.13.2 --amend --no-edit rules are unchanged.

CLAUDE.md §5 Mechanics and its workflow-init copy (identical) now recommend
`git commit -m 'WIP: …'`, state what else is accepted and the after-commit condition;
docs/architecture.md and docs/getting-started.md point to those rules. The WIP note no longer
promises the counters are kept. Tests run real commits between PreToolUse and PostToolUse
under sh and dash for every row: plain, harmless hook, rewriting hook, failed commit, chains,
extra -m/-F/--fixup/-e, hook-made extra commits, amend-back, --amend inside the message, no
reflog, corrupt record, background call; each repair's new cases fail on the previous hook.
dev-workflow 0.13.2 -> 0.13.3.

Gate B: six logical passes, each two sequential calls (spec, then quality) against the same
base and head ids; closed on pass 6 with no findings. A small persistent record was added by
the user's decision after pass 2. Pass reports: one tell at pass 3 (finding count rose,
5 -> 9), none reaching the two-tell stop. No story cited, so no evidence entry is owed.

cycle hpg0kyk2nz; floor 3 per none; hook reminder threshold absent
cycle hpg0kyk2nz; Gate B (passes 1-6, codex): Findings 6,5,9,7,1,0. Blockers 0,0,0,0,0,0. Majors 3,2,4,4,1,0.

Human exceptions: none
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 37b52d63-6e85-4fa7-bd7c-f06f148ebd9a

📥 Commits

Reviewing files that changed from the base of the PR and between b02c16a and 1542663.

📒 Files selected for processing (11)
  • .context/codex-reviews/gate-b-quality-p0nhw0wb2d-pass-1.md
  • .context/codex-reviews/gate-b-quality-p0nhw0wb2d-pass-2.md
  • .context/codex-reviews/gate-b-quality-p0nhw0wb2d-pass-3.md
  • .context/codex-reviews/gate-b-spec-p0nhw0wb2d-pass-1.md
  • .context/codex-reviews/gate-b-spec-p0nhw0wb2d-pass-2.md
  • .context/codex-reviews/gate-b-spec-p0nhw0wb2d-pass-3.md
  • CLAUDE.md
  • plugins/dev-workflow/CHANGELOG.md
  • plugins/dev-workflow/commands/workflow-init.md
  • plugins/dev-workflow/hooks/codex-gate.sh
  • plugins/dev-workflow/hooks/codex-gate.test.sh

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The hook now records eligible WIP commit calls and checks the resulting subject and repository history before retaining Gate-B counters. Tests cover commit attribution and reset cases. The changelog and workflow guidance describe the updated conditions.

Changes

WIP commit flow

Layer / File(s) Summary
Command classification and counter lifecycle
plugins/dev-workflow/hooks/codex-gate.sh
The hook classifies eligible commit commands, records per-call repository state, and checks the resulting subject and history before retaining counters. It removes the call record after post-commit handling.
Commit lifecycle regression tests
plugins/dev-workflow/hooks/codex-gate.test.sh
Tests cover successful and failed commits, message rewriting, amend behavior, backgrounded commands, invalid call records, and overlapping calls.
Release guidance and documentation
plugins/dev-workflow/CHANGELOG.md, CLAUDE.md, plugins/dev-workflow/commands/workflow-init.md, docs/architecture.md, docs/getting-started.md, todos.md, plugins/dev-workflow/.claude-plugin/plugin.json
The changelog and guidance describe eligible WIP commit forms and attribution conditions. The plugin version changes from 0.13.2 to 0.13.3.
Gate-B review reports
.context/codex-reviews/gate-b-*.md
The reports contain findings from earlier review passes and no-findings results from later passes.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant PreToolUse
  participant CodexGate as codex-gate.sh
  participant Git
  participant PostToolUse
  PreToolUse->>CodexGate: Classify command and record commit state
  CodexGate->>Git: Execute eligible commit command
  Git-->>PostToolUse: Return command result and repository state
  PostToolUse->>CodexGate: Verify subject, HEAD, and reflog
  CodexGate-->>PostToolUse: Retain or reset counters and remove call record
Loading

Merge Risk: ⚪ Minimal · up to 15426

WIP commits reset Gate-B counters when jq is unavailable, as documented. No actionable merge-blocking issue remains after normal checks.

Architecture Summary

Architecture risk: 🟡 Medium · up to 15426

The change affects 4 systems.

Changed systems: plugins, docs, CLAUDE.md, todos.md

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — plugins (service) was modified; 5 changed files map to changed impact.
  • observed — docs (service) was modified; 2 changed files map to changed impact.
  • observed — CLAUDE.md (service) was modified; 1 changed file maps to changed impact.
  • observed — todos.md (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in docs/architecture.md: The documentation replaces the rule that any commit with a WIP-starting message is cycle-internal with separate rules for a qualifying one-line git commit and, under narrower conditions, git commit --amend --no-edit. It specifies attribution and message checks, a reminder when hooks or settings could rewrite the message, and that other detected commits reset the counters; undetected commits are outside both rules.
  • observed — Modified behavior in docs/getting-started.md: Step 7 changes the commit instruction from a WIP:-prefixed commit to a plain git commit -m 'WIP: …' and replaces the claim that the hook recognizes WIP commits with a reference to the conditions in CLAUDE.md §5 Mechanics for keeping the cycle open.
  • observed — Modified behavior in plugins/dev-workflow/.claude-plugin/plugin.json: The plugin version is updated from 0.13.2 to 0.13.3.
  • observed — Modified behavior in todos.md: The entry replaces the prior account that -m "wip…" trusted the typed message and could keep the cycle despite a message-rewriting hook, and that the corresponding prompt and architecture docs needed a later fix. It now records the 0.13.3 behavior: decide before the commit whether the repository could rewrite the message, then reset afterward only when the WIP result is attributable to the command, for allow-listed one-line git commit commands. It also says §5 Mechanics and both docs now describe the behavior; chained or redirected WIP commits remain open.

Reliability and maintainability

  • inferred — Risk-relevant change factors for plugins: blast_radius_3; direct_dependents_3
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 2 files. (9 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: separate pre-commit and post-commit handling for WIP commits in version 0.13.3.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 2 files. (9 skipped: 9 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks the commit trail,
And stores each call before the hail.
If WIP is proven, counters stay,
If not, the gate resets the day.
The tests hop through each path with care,
While notes explain the rules to share.

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[High risk] Adds code review findings for a development workflow hook.

The PR appears safe to merge; no new actionable issue or outstanding previous finding was identified.

Summary

The PR separates the pre-commit WIP reminder from the post-commit counter decision and gives each tool call its own attribution record.

  • It updates the WIP guidance and release version.
  • It adds real-commit lifecycle tests, including overlapping calls and malformed IDs.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[PreToolUse] --> B[Check command and show reminder or WIP note]
  A --> C[Record HEAD, reflog length, and amend mode by call ID]
  C --> D[Commit attempt]
  D --> E[PostToolUse]
  E --> F{WIP subject and attributable result?}
  F -->|Yes| G[Keep Gate-B counters]
  F -->|No| H[Reset Gate-B counters]
Loading

Reviews (2) · Last reviewed commit: "Keep one -m wip record per tool call (PR..."

Comment thread plugins/dev-workflow/hooks/codex-gate.sh
Greptile on PR #31: the attribution record was one shared file, so overlapping tool calls
could take each other's record. Both directions were real, reproduced as regressions on the
PR head: two valid WIP calls lost their counters (Greptile's order), and a call whose commit
a hook had rewritten into a real one kept the counters on the next call's record (the
reviewer's counter-case).

Each call now has its own record, .context/codex-gate.wipBase.<tool_use_id>. The id is read
with jq as a top-level string, checked there (1-100 chars of [A-Za-z0-9_-]) before any shell
capture, and encoded injectively into lower case (`_` -> `__`, X -> `_x`) so ids differing
only in case stay apart on a case-insensitive filesystem. A missing, malformed or nested-only
id, and every call without jq (whose fallback reader cannot tell top level from nested),
gets no record, so the WIP commit resets - the safe direction. Mechanics copies (identical),
CHANGELOG and the hook comment say so. New tests: the two interleavings, malformed ids,
jq-free nested id, and ids differing only in case; each fails on the hook it fixes.

Gate B: three logical passes, each two sequential calls (spec, then quality) against the same
base and head ids; closed on pass 3 with no findings. No story cited, so no evidence entry is
owed.

cycle p0nhw0wb2d; floor 3 per none; hook reminder threshold absent
cycle p0nhw0wb2d; Gate B (passes 1-3, codex): Findings 4,2,0. Blockers 0,0,0. Majors 4,2,0.

Human exceptions: none
@dsnger
dsnger merged commit 85faa49 into main Sep 29, 2026
3 checks passed
@dsnger
dsnger deleted the fix-wip-message-pre-post branch September 29, 2026 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant