Skip to content

feat(workflow): enforce fresh base branch and add local governance check - #62

Merged
yohnark merged 3 commits into
mainfrom
fix/61-codex-session-findings
Aug 7, 2026
Merged

yohnark merged 3 commits into
mainfrom
fix/61-codex-session-findings

Conversation

@yohnark

@yohnark yohnark commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix two of the four performance issues found in today's codex sessions (Issue #48, #25, mottainai config): stale base branches slipping past task start, and PR governance checks only surfacing after CI runs.

Linked issue

Closes #61

Scope

Included

  • policy.worktree.staleBaseBranch policy flag (default off, enforce on strict-worktree, advisory on standard) plus checkStaleBaseBranch in startTask that rejects task starts when the local base branch trails origin/<branch>.
  • scripts/governance-check-local.mjs (pnpm run governance:pr:local): runs the existing validatePullRequest and validateBranchName against local git state (title/body/diff/branch) before gh pr create, instead of only after CI.
  • scripts/governance-check-issue-local.mjs (pnpm run governance:issue:local): local equivalent of validate-issue.mjs for checking a draft issue body before gh issue create. Added after this PR's own first two pushes failed CI on exactly the gaps these two commands close (non-compliant branch name, then a missing "Implementation notes" section on the linked issue) — see PR discussion.

Excluded

  • architecture:check local/CI unification — already solved on PR feat(ci): enforce coding standards and architecture boundaries #59 via verify:standards, no change needed here.
  • Worktree bootstrap MCP config copying — investigated and found unnecessary; Mottainai MCP registration lives in the global ~/.codex/config.toml, not per-worktree, and the actual failure (unresolved global bin) was already fixed in a separate session.

Implementation

  • checkStaleBaseBranch compares local baseCommit against origin/<baseBranch> via git merge-base --is-ancestor; only rejects when local is a strict ancestor of the remote tip (avoids false positives on diverged/ahead branches). No implicit git fetch — it only checks what's already known locally.
  • governance-check-local.mjs reuses validatePullRequest and validateBranchName from governance-lib.mjs unchanged; only the input-resolution layer (title from --title or last commit subject, body from --body-file or last commit body, files from --files or git diff --name-only, branch from --branch or git branch --show-current) is new.
  • governance-check-issue-local.mjs reuses validateIssue from governance-lib.mjs unchanged; same input-resolution pattern via --body-file/--body.

Behavioral changes

  • Task start can now fail with unsupported-repo-state when staleBaseBranch=enforce and the local branch is behind origin. Only affects strict-worktree preset by default; existing standard/minimal presets are unaffected (advisory/off).
  • New optional local commands pnpm run governance:pr:local and pnpm run governance:issue:local; no change to existing governance:pr/governance:issue (CI) behavior.

Validation

  • Typecheck
  • Tests
  • Build
  • Package check

Risks

  • staleBaseBranch check relies on the local repo already having an up-to-date origin/<branch> ref; it does not fetch, so a caller who never fetches gets no protection (documented in code comment). Low risk since it's opt-in via policy and defaults to off.

Breaking changes

No.

Review focus

  • Whether strict-worktree defaulting staleBaseBranch to enforce is the right call, or if it should start at advisory for a rollout period.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@yohnark, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 1 minute

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b16326c-0803-4831-bfd5-0e03040586e6

📥 Commits

Reviewing files that changed from the base of the PR and between 273b324 and ef38660.

📒 Files selected for processing (9)
  • package.json
  • scripts/governance-check-issue-local.mjs
  • scripts/governance-check-issue-local.test.mjs
  • scripts/governance-check-local.mjs
  • scripts/governance-check-local.test.mjs
  • src/workflow/domain/task.test.ts
  • src/workflow/domain/task.ts
  • src/workflow/policy/presets.ts
  • src/workflow/policy/schema.ts

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

yohnark and others added 3 commits August 7, 2026 22:59
startTask now rejects task starts where the local base branch trails
origin/<branch> when policy.worktree.staleBaseBranch=enforce, preventing
CI from seeing files the local branch point never saw (root cause behind
PR #59's post-merge boundary gaps).

Also adds governance:pr:local, a CLI wrapper around the existing
validatePullRequest that lets PR title/body/files be checked locally
before gh pr create, instead of only after CI runs validate-pr.mjs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ed PR/issue pushes

governance:pr:local didn't check branch name, so a non-compliant branch
name (fix/codex-session-findings, missing an issue number) only surfaced
after CI ran validate-branch-name.mjs. It now also runs validateBranchName
before reporting success.

There was no local equivalent of validate-issue.mjs at all, so an issue
body missing the exact "Implementation notes" heading only surfaced after
CI ran validate-issue.mjs on a linked issue. Adds governance:issue:local
as the same kind of CLI wrapper governance:pr:local already is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ory mode

checkStaleBaseBranch() returned { stale: false } whenever the underlying
git call didn't complete (missing ref, timeout, spawn failure, output
limit), conflating "check failed to run" with "branch is not stale."
Under staleBaseBranch=enforce this fail-opened exactly the git errors
enforce is meant to guard against, contrary to the fail-closed pattern
already established in resolveRepoState()'s usable/ok distinction.

checkStaleBaseBranch() now returns a four-state result (fresh/stale/
unavailable/unknown) that separates "no tracking ref" from "git call
did not complete." startTask() blocks on both stale and unknown when
staleBaseBranch=enforce, and no longer treats a failed git call as
equivalent to a fresh branch.

staleBaseBranch=advisory was also a no-op — only the enforce branch
ran the check at all, so advisory behaved identically to off despite
the standard preset setting it explicitly. advisory now runs the same
check and surfaces stale/unknown results as structured warnings on
StartTaskResult without blocking the task start.
@yohnark
yohnark force-pushed the fix/61-codex-session-findings branch from 4a92145 to ef38660 Compare August 7, 2026 14:00
@yohnark
yohnark merged commit 88c3854 into main Aug 7, 2026
10 checks passed
@yohnark
yohnark deleted the fix/61-codex-session-findings branch August 7, 2026 14:16
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.

perf(workflow): stale base branches and missing local governance check surfaced by codex sessions

1 participant