Skip to content

feat(goals): track line changes per goal - #415

Merged
andrei-hasna merged 4 commits into
mainfrom
factory/task-f95f0749a541-411a862c
Jul 28, 2026
Merged

feat(goals): track line changes per goal#415
andrei-hasna merged 4 commits into
mainfrom
factory/task-f95f0749a541-411a862c

Conversation

@andrei-hasna

@andrei-hasna andrei-hasna commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Capture net added/deleted lines from local Git worktree snapshots per goal turn while excluding pre-existing changes.
  • Persist line totals on goals and goal-plan nodes, aggregate plan totals, and expose them through app-server v2 schemas and TUI goal/status views.
  • Preserve legacy payload/default behavior and disable LOC attribution for remote or multi-environment turns without one authoritative local worktree.
  • Keep the codex-goal-extension lib target at test = false; LOC tests use the existing integration-test surface.

P1 repair design

  • Same-CWD ownership is exclusive across processes. A persistent codewith-line-change-accounting.lock in the linked worktree private Git directory is opened without truncation and held with File::try_lock() for the goal-turn baseline lifetime. The process-local registry adds owner/refcount semantics; the filesystem lock is the cross-process authority.
  • Lock resolution/open/acquisition failure suppresses the contender baseline and LOC accounting. The winner counts normally; the losing overlapping turn remains LOC-suppressed until a fresh turn can acquire a fresh baseline, preferring omission over double or false attribution.
  • Tool completion carries a host-owned NoWorktreeMutation / MaybeMutatesWorktree signal. Proven read-only first-party tools and MCP tools with readOnlyHint=true skip worktree capture while preserving token/time accounting; unknown, dynamic, shell, patch, and other credible mutation paths conservatively capture.
  • Turn stop/error and goal lifecycle reconciliation still force capture. Existing Git snapshot semantics for staged, unstaged, untracked, deleted, binary, ignored, and linked-worktree cases are unchanged.

Verification

  • Blacksmith Testbox 30316026777 on exact SHA e04b0e2bcfc31017b87592c6d7270cb1787de7d5: pass. Scoped test compilation, Git snapshot tests, all goal accounting integration tests, the subprocess shared-CWD lease regression, read-only no-rescan regression, parallel completion regression, and core lifecycle dispatch/classification regressions passed.
  • Blacksmith Testbox 30316709172 on the same exact SHA: pass. Scoped just fix completed with no diff; Just format check and cargo fmt --all -- --config imports_granularity=Item --check from codex-rs passed.
  • Testbox 30316046857 was superseded after scoped just fix completed cleanly; its only failure was the gate command targeting the virtual workspace manifest without --all. Replacement 30316709172 corrected the command and passed.
  • Local just fmt, git diff --check, staged gitleaks before each commit/push, and full-candidate gitleaks: pass.

Residual tradeoffs

  • Advisory locking relies on the host filesystem honoring standard OS file locks. The lock file is intentionally persistent so all contenders address a stable inode; process exit releases the held lock.
  • Read-only classification is explicit and conservative. Newly added or uncertain tools default to MaybeMutatesWorktree, preserving correctness at the cost of a scan until they are proven read-only.

Run run_8be47d216111 · backend codewith · task inline
🏭 Generated by @hasnaxyz/factory


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@andrei-hasna
andrei-hasna force-pushed the factory/task-f95f0749a541-411a862c branch 3 times, most recently from f73fd20 to 4241b44 Compare July 27, 2026 22:42
@andrei-hasna
andrei-hasna force-pushed the factory/task-f95f0749a541-411a862c branch from 4241b44 to 2b30fde Compare July 27, 2026 22:53
@andrei-hasna andrei-hasna changed the title feat: Track lines of code changed per goal — per goal-plan node and overall — and display it in the goal UI. — Start a goal pl feat(goals): track line changes per goal Jul 27, 2026
@andrei-hasna andrei-hasna added the code-reviewed Reviewed by Codewith label Jul 27, 2026

@andrei-hasna andrei-hasna left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REVIEW_RESULT: request_changes

GitHub rejected a CHANGES_REQUESTED review because the active account (andrei-hasna) authored this PR. These findings apply to commit 2b30fde:

[P1] Prevent cross-goal double counting in shared worktrees - codex-rs/ext/goal/src/line_changes.rs:58
stats_since_baseline diffs the entire repository from a per-goal baseline, without a thread/goal ownership boundary. If two active threads use the same cwd (which manual/shared worktree sessions support), each snapshot includes both threads' edits, so both goals record the combined additions/deletions and a plan aggregate double-counts them. The result depends on interleaving rather than goal ownership. Add per-worktree exclusion/unique-worktree enforcement or tool-owned delta attribution, with a same-cwd concurrent-goals regression test.

[P1] Avoid a full repository snapshot after every completed tool - codex-rs/ext/goal/src/accounting.rs:291, codex-rs/ext/goal/src/extension.rs:445, codex-rs/git-utils/src/worktree_snapshot.rs:120
Once a line-change baseline exists, progress_snapshot always returns line_changes even when token and time deltas are zero. on_tool_finish therefore snapshots after every completed non-goal tool, including read-only tools, and each snapshot initializes a temporary index then executes git add --all and write-tree across the repository. On this 5,779-file checkout, one no-op snapshot took about 0.77 seconds, so tool-heavy turns repeatedly pay that latency and larger repositories will be worse. Gate this work on a mutation/change signal or use a cached/incremental strategy, and add a regression that proves read-only tool completion does not rescan the whole worktree.

@andrei-hasna
andrei-hasna merged commit 2968352 into main Jul 28, 2026
29 of 30 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

code-reviewed Reviewed by Codewith

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant