Skip to content

feat: implement issue #809 — upsert_gitignore_baseline must preserve baseline negations + migrate unmarkered baselines (blocks #800 apply) - #815

Merged
don-petry merged 6 commits into
mainfrom
dev-lead/issue-809-20260719-2153
Jul 19, 2026
Merged

feat: implement issue #809 — upsert_gitignore_baseline must preserve baseline negations + migrate unmarkered baselines (blocks #800 apply)#815
don-petry merged 6 commits into
mainfrom
dev-lead/issue-809-20260719-2153

Conversation

@don-petry

@don-petry don-petry commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Closes #809

Implemented by dev-lead agent. Please review.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented duplicate or conflicting .gitignore patterns from overriding baseline exceptions.
    • Preserved required exclusions while ensuring allowed files, such as examples and public assets, remain accessible.
    • Improved migration of existing unmarked baselines into a single managed block.
    • Ensured repeated baseline updates are idempotent and avoid unnecessary file changes.
  • Tests

    • Added coverage for overlapping patterns, wildcard variations, migration behavior, and repeated updates.

…baseline negations + migrate unmarkered baselines (blocks #800 apply)
@don-petry
don-petry requested a review from a team as a code owner July 19, 2026 22:03
Copilot AI review requested due to automatic review settings July 19, 2026 22:03
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 51 minutes

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 36c2d4ca-5648-48fe-ad25-9a95a8f47439

📥 Commits

Reviewing files that changed from the base of the PR and between aa7a572 and 1a36dcc.

📒 Files selected for processing (2)
  • test/scripts/compliance-remediate/gitignore-baseline.bats
  • test/scripts/sync-gitignore-baseline/dry-run.bats
📝 Walkthrough

Walkthrough

upsert_gitignore_baseline now neutralizes conflicting L2 patterns, preserves baseline negations, migrates unmarked baselines into one managed block, and validates behavior through Bats tests covering ignore precedence, preservation, and idempotency.

Changes

Gitignore baseline neutralization

Layer / File(s) Summary
L2 neutralization helper
scripts/lib/gitignore-baseline.sh
Adds idempotent filtering of duplicated baseline patterns, blank-line cleanup, and conditional re-emission of baseline negations while retaining repository-specific entries.
Upsert integration
scripts/lib/gitignore-baseline.sh
Applies neutralization to marker-less content and post-marker L2 content before emitting the updated .gitignore.
Behavioral regression coverage
test/scripts/lib/gitignore-baseline.bats
Tests broad and non-identical ignore patterns, preserved entries, unmarked-baseline migration, and repeated-upsert idempotency using git check-ignore.

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

Sequence Diagram(s)

sequenceDiagram
  participant ExistingGitignore
  participant upsert_gitignore_baseline
  participant _gib_neutralize_l2
  participant UpdatedGitignore
  ExistingGitignore->>upsert_gitignore_baseline: provide marker-less or marker-present content
  upsert_gitignore_baseline->>_gib_neutralize_l2: pass existing L2
  _gib_neutralize_l2->>upsert_gitignore_baseline: return filtered L2 and effective negations
  upsert_gitignore_baseline->>UpdatedGitignore: emit managed baseline plus neutralized L2
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the main change: preserving gitignore baseline negations and migrating unmarkered baselines.
Linked Issues check ✅ Passed The changes and tests match #809's requirements for negation preservation, unmarkered-baseline migration, and idempotent marker handling.
Out of Scope Changes check ✅ Passed The diff appears scoped to gitignore-baseline logic and its Bats coverage, with no unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev-lead/issue-809-20260719-2153

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

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

@don-petry

Copy link
Copy Markdown
Contributor Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) July 19, 2026 22:04

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a neutralization mechanism (_gib_neutralize_l2) in the gitignore baseline script to prevent duplicate or conflicting patterns in the L2 block from overriding baseline negations. It also adds corresponding tests in BATS to verify this behavior. Feedback suggests stripping carriage returns (\r) before passing text to awk to prevent CRLF issues, and utilizing $BATS_TEST_TMPDIR when creating temporary directories in tests to ensure proper isolation and cleanup.

Comment thread scripts/lib/gitignore-baseline.sh
Comment thread test/scripts/lib/gitignore-baseline.bats
@don-petry
don-petry disabled auto-merge July 19, 2026 22:05
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 19, 2026
@don-petry

Copy link
Copy Markdown
Contributor Author

Dev-Lead — fix-reviews (applied)

Changes committed and pushed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the org-wide .gitignore baseline upsert helper to address issue #809 by preventing baseline negations from being overridden by later per-repo patterns, and by folding legacy unmarker-ed baselines into the single managed marker-wrapped block (instead of duplicating them).

Changes:

  • Add _gib_neutralize_l2 and apply it during both “insert-on-top” and “replace-in-place” upsert flows to drop L2 lines that duplicate baseline pattern lines.
  • Extend bats coverage with git-semantic assertions (git check-ignore) for the public.pem re-hide regression and for unmarker-ed baseline migration/idempotency.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
scripts/lib/gitignore-baseline.sh Adds L2 “neutralization” logic and applies it when inserting/replacing the managed baseline block.
test/scripts/lib/gitignore-baseline.bats Adds #809 regression tests using git check-ignore, plus migration + idempotency coverage.

Comment thread scripts/lib/gitignore-baseline.sh
Comment thread test/scripts/lib/gitignore-baseline.bats
@don-petry
don-petry disabled auto-merge July 19, 2026 22:08
@donpetry-bot

Copy link
Copy Markdown
Contributor

CI checks on this PR are still running. Once they complete, re-mention @donpetry-bot to trigger a fresh review.

Posted by the donpetry-bot PR-review cascade.

@don-petry

Copy link
Copy Markdown
Contributor Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) July 19, 2026 22:24
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 19, 2026
@don-petry
don-petry disabled auto-merge July 19, 2026 22:24
@don-petry
don-petry enabled auto-merge (squash) July 19, 2026 22:35
@don-petry
don-petry disabled auto-merge July 19, 2026 22:35
@don-petry don-petry added the dev-lead:hands-off Exclude this PR/issue from the dev-lead agent label Jul 19, 2026
@don-petry

Copy link
Copy Markdown
Contributor Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) July 19, 2026 22:41
…ixtures

#809 gave upsert_gitignore_baseline a negation re-allow tail (to defend against
non-identical L2 globs like **/*.pem re-hiding !public.pem). That changed the
idempotent steady state to block + neutralized-L2 + tail. Two older fixtures
(#798 sync dry-run, #808 remediate) fed the raw canonical (tail-less) as
'already current', so the current-baseline skip/no-op detection saw a diff and
planned a PR. Feed those fixtures the actual upsert steady state instead. Upsert
is idempotent from the 2nd application (verified), so this is the true no-op input.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fa6TNhxEXj6WAKpaJLHvNK
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/lib/gitignore-baseline.sh`:
- Around line 79-87: The migration currently preserves canonical header comments
from an old L2 baseline, allowing them to duplicate the newly emitted block.
Update _gib_neutralize_l2 to remove only exact matches of the block’s own
canonical comment lines while continuing to preserve unrelated comments;
document the chosen limitation if comments remain intentionally preserved. In
test/scripts/lib/gitignore-baseline.bats lines 280-315, extend the TalkTerm
fixture with the header comment and assert the migration produces the intended
non-duplicated result.
- Around line 88-131: Update _gib_neutralize_l2 so the block reaches awk without
-v escape processing, preserving literal gitignore backslashes such as \!, \#, \
, and foo\bar. Export the block through the GIB_NEUTRALIZE_BLOCK environment
variable and read it via ENVIRON inside awk, leaving the existing split and drop
matching behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6d939fb8-9f60-415d-a1fa-5006b406636d

📥 Commits

Reviewing files that changed from the base of the PR and between 45a6cc9 and aa7a572.

📒 Files selected for processing (2)
  • scripts/lib/gitignore-baseline.sh
  • test/scripts/lib/gitignore-baseline.bats

Comment thread scripts/lib/gitignore-baseline.sh
Comment thread scripts/lib/gitignore-baseline.sh
@donpetry-bot

donpetry-bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor
Superseded by automated re-review at 1a36dccafea8c34c2bfb826a0ce4bd94da394337 — click to expand prior review.

Review — fix requested (cycle 1/3)

The automated review identified the following issues. Please address each one:

Findings to fix

Automated review — NEEDS HUMAN REVIEW

Risk: MEDIUM
Reviewed commit: 1a36dccafea8c34c2bfb826a0ce4bd94da394337
Cascade: triage → deep (triage: haiku 4.5 → deep: opus 4.8 + duck: o4-mini → audit: fable 5)

Summary

PR #815 adds _gib_neutralize_l2 to the shared .gitignore baseline upsert lib so L2 patterns can't re-hide baseline-negated paths (!public.pem, !.env.example) and folds legacy unmarkered baselines into one block; it is well-tested with real git check-ignore semantics and all CI is green (ShellCheck, CodeQL, gitleaks, SonarCloud, AgentShield). Risk is MEDIUM (non-trivial logic on a shared shell lib; no auth/secrets/crypto/migrations, no injection). Escalating on a failing gate: reviewDecision is CHANGES_REQUESTED (CodeRabbit) leaving mergeStateStatus BLOCKED, and one finding — awk -v escape-processing of the block — is a valid latent correctness gap. No Tier-3 security audit needed. Downstream impact: (none).

Findings

  • major: awk -v block="$block" applies backslash-escape processing to the block value, so the drop[] set and negation tail are built from escape-mangled text. A baseline pattern containing a literal backslash (gitignore escapes like !, #, or a trailing-space escape) would not exactly-match its L2 counterpart (read verbatim via $0) and would fail to neutralize/duplicate-fold. LATENT: the current canonical baseline contains no backslashes, so there is no present-day impact, but this is a robustness gap on a shared lib. CodeRabbit's suggested fix (pass the block via a GIB_NEUTRALIZE_BLOCK env var and read it through awk ENVIRON) avoids the -v escape pass.
  • minor: Migration folds L2 pattern lines but intentionally never drops comment lines, so an old unmarkered baseline's canonical header comments can survive and duplicate the newly emitted block header. The author documented this as a deliberate tradeoff (dropping comments risks clobbering a repo's own comments). Acceptable as a cosmetic limitation; only worth tightening to drop exact matches of the block's own canonical comment lines if duplicate headers prove noisy.
  • info: Advisory bot suggestions are already satisfied at head: Gemini's CRLF concern is handled (block and stdin are both stripped with tr -d '\r' at lines 41-42) and the BATS temp-dir isolation suggestion is met (_gib_check_ignored uses mktemp -d "$BATS_TEST_TMPDIR/stub.XXXXXX"). Codex posted a usage-limit message (no review). SonarCloud Quality Gate passed with 0 new issues.
  • info: mergeStateStatus BLOCKED is driven by a CHANGES_REQUESTED review from the coderabbitai bot (not a human org-leads reviewer). All status checks are green. The block clears once the CodeRabbit findings are resolved/dismissed. run_secret_scanning MCP tool is not exposed in this environment; gitleaks CI check passed and the diff contains no secret material.

Reviewed by the PR-review cascade (triage: haiku 4.5 → deep: opus 4.8 + duck: o4-mini → audit: fable 5). Reply if you need a human review.

Additional tasks

  1. Resolve all unresolved review thread comments from other reviewers
  2. Ensure all CI checks pass after your changes
  3. Rebase on the target branch if behind
  4. Do NOT modify files unrelated to the findings above

The review cascade will automatically re-review after new commits are pushed.

@donpetry-bot donpetry-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: 1a36dccafea8c34c2bfb826a0ce4bd94da394337
Review mode: triage-approved (single reviewer)

Summary

PR #815 fixes the #809 correctness regression in the shared .gitignore baseline lib: _gib_neutralize_l2 drops L2 lines that exactly duplicate block pattern lines (migrating old unmarkered baselines without duplication) and re-emits all baseline negations as a re-allow tail after L2, so broad L2 globs (.pem, .env, **/*.pem) can never re-hide baseline-negated paths (!public.pem, !.env.example). Both prior escalation reasons are now cleared: CodeRabbit's CHANGES_REQUESTED became an APPROVED review after its two findings were adjudicated and withdrawn, and the awk -v escape-processing finding was resolved by the repo owner as a latent non-issue (the canonical baseline contains no backslash-bearing patterns) with CodeRabbit formally withdrawing the comment. No new commits since; head SHA unchanged. Risk MEDIUM (non-trivial logic on a shared shell lib), no HIGH-risk surface.

Linked issue analysis

Closes #809. All required acceptance criteria are substantively met with bats tests asserting real git semantics via git check-ignore in temp git-init dirs: (1) markets-like and google-app-scripts-like inputs — public.pem NOT ignored after upsert while secret.pem stays ignored; (2) TalkTerm-like unmarkered baseline — exactly one BEGIN/END marker pair, .env and .pem appear once, genuine L2 (node_modules/, dist/, .log, .DS_Store) preserved; (3) idempotency — second upsert on its own output is byte-identical; (4) beyond the issue's ask, non-identical glob cases (.env vs !.env.example, **/.pem vs !public.pem) are covered by the re-allow tail with dedicated tests. Two pre-existing steady-state tests were correctly updated to define "current" as the upsert steady state.

Findings

  • No blocking findings.
  • Prior cascade's major finding (awk -v block escape-processing could mangle backslash-bearing block lines) is LATENT with no present-day impact: the canonical baseline carries only glob patterns with no backslashes. The owner resolved the thread as a non-issue and CodeRabbit withdrew the comment and approved. Reasonable adjudication; ENVIRON would be a stylistic hardening, not a correctness fix.
  • Prior cascade's minor finding (old unmarkered baseline header comments may duplicate in L2) was accepted by the owner as a cosmetic limitation — comments have no gitignore semantics; dropping them would risk clobbering repo-authored comments. CodeRabbit concurred and withdrew.
  • All 6 inline review threads (Gemini CRLF, BATS temp-dir isolation, Copilot non-identical-glob gap, Copilot core.excludesfile determinism, CodeRabbit comment-dup, CodeRabbit awk -v) are resolved, with fixes verified present at head (tr -d '\r' at lib lines 41-42; mktemp under BATS_TEST_TMPDIR; re-allow tail + tests; git -c core.excludesfile=/dev/null).
  • run_secret_scanning MCP tool not exposed in this environment; gitleaks CI passed and the diff contains no secret material.
  • Neutralization logic reviewed for idempotency and edge cases (comment-only L2 emits no tail, blank-squeeze, marker replace-in-place path also neutralized) — sound.

CI status

All required checks green at head 1a36dcc: ShellCheck, Lint, Lint and bats, CodeQL (actions), SonarCloud Quality Gate, Secret scan (gitleaks), Agent Security Scan, AgentShield, npm audit, CodeRabbit (SUCCESS). A few dev-lead dispatch/ci-relay runs show CANCELLED/SKIPPED — these are superseded duplicate runs; the latest same-name runs succeeded. Ecosystem audits (pip/cargo/govulncheck/pnpm) skipped as not applicable. mergeStateStatus BLOCKED solely reflects the pending required review, which this approval addresses.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@don-petry
don-petry merged commit d1254f7 into main Jul 19, 2026
51 of 65 checks passed
@don-petry
don-petry deleted the dev-lead/issue-809-20260719-2153 branch July 19, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev-lead:hands-off Exclude this PR/issue from the dev-lead agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

upsert_gitignore_baseline must preserve baseline negations + migrate unmarkered baselines (blocks #800 apply)

3 participants