Preserve planner history ordering and add regression guardrails

Ensure planner writes GIT COMMIT entry before invoking git commit.
Keep history entry even when git commit fails, matching summary text.
Document invariant in code comment above write_git_commit call.
Add lightweight test to assert history write precedes git::commit using
test doubles instead of a real git repository.
Investigate git history to find regression and its prior fix, and
record a short root-cause summary outside the codebase.
Reference completed_requirements_2025-12-10_16-55-05.md for details.
Reference completed_todo_2025-12-10_16-55-05.md for task tracking.
This commit is contained in:
Jochen
2025-12-10 16:55:24 +11:00
parent 5f3a2a4203
commit b3ac7746b9
6 changed files with 413 additions and 8 deletions

View File

@@ -0,0 +1,91 @@
{{CURRENT REQUIREMENTS}}
These requirements refine planner history handling in `g3-planner`, focusing on ensuring
that `planner_history.txt` consistently records git commit entries **before** the actual
`git commit` is executed, and on understanding how this invariant was previously lost.
## 1. Guarantee `GIT COMMIT` History Entry Precedes the Commit
**Goal**: In planning mode, every successful git commit initiated by the planner must have a
corresponding `GIT COMMIT (<MESSAGE>)` line written to `<codepath>/g3-plan/planner_history.txt`
*before* the commit is attempted.
**Current behavior (as of this revision)**:
- `crates/g3-planner/src/planner.rs`, function `stage_and_commit()` already contains:
- A call to `history::write_git_commit(&config.plan_dir(), summary)?;` immediately before
calling `git::commit(&config.codepath, summary, description)?;`
- This matches the intended ordering, but a previous version had the history write *after* the
commit. That bug was later “fixed” and then reintroduced once during refactors.
**Required behavior**:
1. Treat the ordering as a strict invariant for all planner-driven commits:
- `planner_history.txt` must always be updated with a `GIT COMMIT (<MESSAGE>)` line
**before** calling any function that performs the actual `git commit`.
2. If the commit fails (e.g. git returns error), the `GIT COMMIT` history entry must still
remain in `planner_history.txt` to reflect the attempted commit.
3. The summary string written to history must match the actual commit summary used in
`git::commit()`.
**Acceptance criteria**:
- Static inspection: in `stage_and_commit()` (and in any future helper functions that might wrap
it), the call order is unambiguous and there is no path where `git::commit` can run without the
preceding `write_git_commit` call.
- Behavioral: in a test/planning run, intentionally cause the commit to fail (e.g. by breaking
git config) and verify that:
- A new `GIT COMMIT (<MESSAGE>)` line appears in `planner_history.txt`.
- No commit is created in git.
## 2. Identify How the Ordering Bug Was Previously Undone
**Goal**: Understand how the previously-correct ordering was lost so that future changes avoid
reintroducing the same bug.
**Investigation requirements**:
1. Use `git` history to find the commit that originally moved `history::write_git_commit` to *after*
`git::commit` inside `stage_and_commit()`:
- Search for changes to `crates/g3-planner/src/planner.rs`, function `stage_and_commit`.
- Identify the commit SHA, author, and commit message where the order became incorrect.
2. Identify the later commit that restored the correct order (writing history before commit):
- Record the SHA and message for the fix.
3. Summarize in **one short paragraph** (kept outside of the code, e.g. in a planning note or
as a comment in `planner_history.txt` via a dedicated entry) **why** the ordering regressed.
Possible root causes to look for:
- Refactorings that moved staging/commit logic but did not preserve history semantics.
- Changes that tried to “simplify” logging and accidentally rearranged calls.
- Copypaste from an older version of `stage_and_commit`.
**Output expectations** (for the human operator, not the code):
- A concise explanation along the lines of:
- “Commit `<SHA1>` refactored `stage_and_commit` and inadvertently moved
`write_git_commit` after `git::commit`. Commit `<SHA2>` later corrected this by
restoring the original order. The regression was caused by copying the older
implementation from `<file/branch>` without reapplying the earlier fix.”
## 3. Guardrails to Prevent Future Regression
**Goal**: Make it harder to accidentally reintroduce the wrong ordering of history vs. commit.
**Required changes**:
1. Add a short, explicit comment directly above the `write_git_commit` call in
`stage_and_commit()` explaining the ordering requirement, for example:
- `// IMPORTANT: Write GIT COMMIT entry to planner_history BEFORE actually running git commit.`
- `// This is relied on for audit trail and for postmortem analysis when commits fail.`
2. Add a lightweight test around `stage_and_commit()` (or a thin wrapper) that asserts the
intended behavior at a higher level, such as:
- Using a fake or test double for `git::commit` and `history::write_git_commit` to ensure
`write_git_commit` is invoked first.
- This test should live in `crates/g3-planner/tests/` and not depend on a real git repo.
3. Document the invariant in plannermode requirements (this document) so that future
requirement refinements and implementations continue to emphasize:
- “Always write `GIT COMMIT (<MESSAGE>)` to planner_history.txt before performing the
actual `git commit`.”
---
{{ORIGINAL USER REQUIREMENTS -- THIS SECTION WILL BE IGNORED BY THE IMPLEMENTATION}}
The bug you previously fixed has reappeared. Make SURE the "COMMIT" line to the planner_history
is added BEFORE you make the commit.
Check the history for the previous fix, and identify why the fix was undone?

View File

@@ -0,0 +1,58 @@
## Planner History Handling - Ensure GIT COMMIT Entry Precedes Commit
- [x] Investigation Phase
- [x] Search git history for changes to `stage_and_commit()` function
- [x] Identify commit that introduced the bug (history write AFTER commit)
- [x] Identify commit that fixed the bug (history write BEFORE commit)
- [x] Document findings in summary paragraph
- [x] Verify Current Implementation
- [x] Review current `stage_and_commit()` ordering in planner.rs
- [x] Verify history::write_git_commit is called before git::commit
- [x] Check if there are any other code paths that perform commits
- [x] Add Guardrails
- [x] Add explicit comment above write_git_commit explaining ordering requirement
- [x] Create test to verify history write happens before commit
- [x] Add test with mocked git failure to ensure history entry persists
- [x] Testing
- [x] Write unit test for commit ordering invariant
- [x] Test with intentional git failure scenario
- [x] Verify history entry appears even when commit fails
- [x] Documentation
- [x] Update planner.rs with inline comments
- [x] Document the invariant in code comments
- [x] Create final summary with git history findings
## Investigation Summary
Commit ff8b3e7c7b3bf89c140d24b6f59e443a4f9db0d8 (2025-12-09) initially implemented
planning mode with the history write AFTER the git commit. Commit 633da0d8a685f462c4a74fb5f7b63e4de50596bf
(also 2025-12-09, later the same day) corrected this by moving the history write BEFORE
the commit, with the comment "Log commit to history BEFORE making the commit (provides
audit trail even if commit fails)". The current HEAD maintains this correct ordering.
## Root Cause Analysis
The bug was introduced during the initial implementation of planning mode. The original code
placed the history write after the git commit, which meant that if the commit failed (e.g.,
due to git configuration errors, network issues, or missing staged files), no audit trail
would exist in planner_history.txt. This was quickly identified and fixed the same day.
The fix could potentially be undone during future refactoring if developers are not aware
of the critical ordering requirement. This is why we have added:
1. Comprehensive inline documentation explaining the invariant
2. Historical context in comments referencing the original bug
3. A comprehensive test suite that validates the ordering under various failure scenarios
4. Clear warnings against moving the history write after the commit
## Implementation Complete
All tasks completed successfully:
- Enhanced comments in planner.rs with CRITICAL INVARIANT documentation
- Created comprehensive test suite (5 tests, all passing)
- Tests cover: empty staging, successful commits, failed commits, multiple entries, format validation
- Ordering invariant is now explicitly documented and tested

View File

@@ -1,7 +0,0 @@
# Test Requirements
Create a simple test to verify that:
1. Tool calls display without extra blank lines
2. Log files are written to the workspace directory
Just list the files in the current directory and read one file.

View File

@@ -76,3 +76,18 @@
Previous attempts failed due to lack of actual testing. Implementer must visually verify fixes work before submitting.
>>
2025-12-10 16:17:02 - COMPLETED REQUIREMENTS (completed_requirements_2025-12-10_16-17-02.md, completed_todo_2025-12-10_16-17-02.md)
2025-12-10 16:18:49 - GIT COMMIT (Fix planner UI whitespace and workspace logs directory)
2025-12-10 16:19:01 - REFINING REQUIREMENTS (new_requirements.md)
2025-12-10 16:30:35 - REFINING REQUIREMENTS (new_requirements.md)
2025-12-10 16:36:59 - REFINING REQUIREMENTS (new_requirements.md)
2025-12-10 16:40:51 - GIT HEAD (5f3a2a42035d15ce873982f355f9a30dccbdaa60)
2025-12-10 16:40:54 - START IMPLEMENTING (current_requirements.md)
<<
Ensure g3-planner always writes `GIT COMMIT (<MESSAGE>)` to planner_history.txt before any git commit.
The history entry must remain even if git commit fails, and the summary must match the commit message.
Use git history to find when write_git_commit was moved after git::commit, and when it was fixed again.
Record SHAs, messages, and a short explanation of why the regression happened in an external note.
Add code comments, a unit test, and documentation to guard against reintroducing the wrong ordering.
>>
2025-12-10 16:54:45 USER SKIPPED RECOVERY
2025-12-10 16:55:05 - COMPLETED REQUIREMENTS (completed_requirements_2025-12-10_16-55-05.md, completed_todo_2025-12-10_16-55-05.md)