Skip to content

Made status --check decide .gitignore presence with the writer's CR-blind test - #55

Merged
dzykovic merged 2 commits into
mainfrom
fix/status-check-crlf
Oct 7, 2026
Merged

dzykovic merged 2 commits into
mainfrom
fix/status-check-crlf

Conversation

@dzykovic

@dzykovic dzykovic commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #45. status --check checked each adapter's .gitignore patterns with its own grep -Fqx. On Linux and macOS a CRLF .gitignore keeps the \r on every line, so present patterns were reported missing, while the .gitignore writer treats them as present — intelligence init changed nothing and the finding never cleared. Git Bash on Windows hid it, because MSYS grep drops the CR.

The writer's presence test, ignore_file_has_line (cli/lib/gitignore.sh), is now the only one: a Bash read loop that strips exactly one trailing CR — as Git itself does — compares literally, and handles a last line without a newline. status --check calls it for ignore and include patterns. The rule text in intelligence/rules/shell.md that claimed "a \r is part of the pattern Git matches" was wrong (Git drops one trailing CR per line; checked on git 2.43 and 2.54) and is corrected, with a pointer to the shared test.

Type of change

  • CLI lifecycle or package behavior
  • Sync engine or adapter
  • Rule, agent, or skill content
  • Documentation
  • Refactor with no behavior change

Public CLI check

  • Uses only the established public command groups (no command changes)
  • Keeps preview/apply behavior explicit for planned writes (unchanged)
  • Covers automatic project alignment and CI refusal through the existing suites
  • Keeps fresh-clone package restoration behind intelligence sync (unchanged)

Verification

Run on Linux, macOS or WSL — on Git Bash grep hides the CR and the old behaviour cannot be observed. Work in a scratch directory outside this checkout; nothing below moves the checkout or its refs. Lay out this branch's runtime first: mkdir rt && git -C <checkout> archive <this PR's head> cli engine packages | tar -x -C rt, and use bash rt/cli/intelligence as the CLI.

  1. git init proj and run init --targets claude in proj. Expected: exit 0; status --check exits 0.
  2. Rewrite proj/.gitignore with CRLF endings in Bash (while IFS= read -r l; do printf '%s\r\n' "$l"; done < .gitignore > g && mv g .gitignore) and delete its CLAUDE.md line. Expected: status --check exits non-zero and names only CLAUDE.md as missing — not .claude/* or !.claude/settings.json, which are still there.
  3. Run init --no-sync. Expected: exit 0; CLAUDE.md is back exactly once and every line of .gitignore still ends in CR; status --check exits 0. A second init --no-sync leaves .gitignore byte-identical.

Automated coverage

  • e2e-negative section 15 runs the steps above on a CRLF .gitignore built in Bash; against the old check.sh in WSL it fails — status --check reported three patterns missing and still "3 problem(s)" after init.
  • unit-gitignore pins ignore_file_has_line: matches with or without the CR including an unterminated last line, no prefix/substring/glob matching, only one CR stripped, a missing file is false.
  • bash cli/tests/verify.sh (scope all, run in WSL) printed verify ok.

Versioned artifacts

  • v0.18.1 is published, so this selects 0.19.0, the version every open release PR shares
  • Engine version, example schema versions, exact sync pins and their lock entries moved together
  • CHANGELOG.md has its line under ## [0.19.0]
  • No stable release is published by this PR

Notes for reviewers

Other grep-style presence checks in cli/ were audited and read LF output the CLI or engine wrote, or validated records; only the .gitignore checks read a CRLF-capable project file.

Copilot AI balanced review requested due to automatic review settings October 7, 2026 13:24
@dzykovic dzykovic added the ai:processing An agent is working on this pull request label Oct 7, 2026

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

The shared CR-aware implementation, regression coverage, and lockstep release artifacts are consistent with the repository contracts.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes #45 by aligning status --check with the CRLF-aware .gitignore writer.

Changes:

  • Reuses ignore_file_has_line for Git policy checks.
  • Adds unit and end-to-end CRLF regression coverage.
  • Updates release artifacts and CR-handling guidance for 0.19.0.
File Description
CHANGELOG.md Records the CRLF fix.
cli/​internal/​check.sh Uses the shared presence test.
cli/​lib/​gitignore.sh Implements literal, CR-aware line matching.
cli/​tests/​e2e-negative.sh Covers CRLF lifecycle behavior.
cli/​tests/​unit-gitignore.sh Tests exact matching and edge cases.
engine/​VERSION Advances the engine to 0.19.0.
intelligence.yaml Updates schema and sync package versions.
intelligence.lock Updates locked engine and sync versions.
intelligence/​rules/​shell.md Corrects CR handling guidance.
examples/​cli-project/​intelligence.yaml Updates version pins.
examples/​dotnet-api-with-react-frontend/​intelligence.yaml Updates version pins.
examples/​dotnet-api-with-react-frontend/​intelligence.lock Updates locked versions.
examples/​go-api/​intelligence.yaml Updates version pins.
examples/​go-api/​intelligence.lock Updates locked versions.
examples/​go-api-with-antigravity/​intelligence.yaml Updates version pins.
examples/​go-api-with-antigravity/​intelligence.lock Updates locked versions.
examples/​go-api-with-opencode/​intelligence.yaml Updates version pins.
examples/​go-api-with-opencode/​intelligence.lock Updates locked versions.
examples/​go-api-with-pi-and-codex/​intelligence.yaml Updates version pins.
examples/​go-api-with-pi-and-codex/​intelligence.lock Updates locked versions.
examples/​platform-with-submodules/​intelligence.yaml Updates version pins.
examples/​platform-with-submodules/​intelligence.lock Updates locked versions.
examples/​with-remote-skills/​intelligence.yaml Updates version pins.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@dzykovic

dzykovic commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Verification - PASS

head: 8034dc5 - steps: PR "Verification" section, steps 1-3 (qa_checks: no match, docs/qa-checks.md does not exist) - env: local

Built from the head commit only: git archive 8034dc5 cli engine packages into a scratch dir outside the checkout, run via bash <rt>/cli/intelligence. Ran in WSL per the PR's own instruction and this host's note that Git Bash's MSYS tools hide the CR this change fixes.

# Step Source Verdict Observed
1 git init proj; init --targets claude in proj. Expected: exit 0; status --check exits 0. PR pass Both exited 0; status --check printed "all good."
2 Rewrite proj/.gitignore CRLF, delete its CLAUDE.md line. Expected: status --check exits non-zero, naming only CLAUDE.md missing. PR pass Fixture confirmed every line CRLF with no CLAUDE.md line before the check. status --check exited 1 with exactly one finding: adapter 'claude' Git policy is missing 'CLAUDE.md'. .claude/* and !.claude/settings.json were not reported.
3 init --no-sync. Expected: exit 0; CLAUDE.md back exactly once, every line still CR-terminated; status --check exits 0; a second init --no-sync leaves .gitignore byte-identical. PR pass Exit 0; CLAUDE.md present exactly once, all 6 lines CRLF. status --check printed "all good." (exit 0). Second init --no-sync produced a byte-identical .gitignore (cmp -s true).

Negative probes (boundary this change names, beyond the declared steps)

  • Double trailing CR on the CLAUDE.md line (CLAUDE.md\r\r): ignore_file_has_line strips exactly one CR, so this should not match. Observed: reported missing, exit 1 — matches the documented one-CR-only contract.
  • Last .gitignore line CR-terminated with no trailing newline at EOF: observed status --check still recognized it as present, exit 0 ("all good") — matches the diff's claim of handling a last line without a newline.
  • Empty .gitignore (0 bytes): all three managed patterns reported missing, no crash, exit 1.

No defects found in the declared steps or the probes.

No standing checks applied — profile qa_checks resolves to docs/qa-checks.md, which does not exist in this repository.

@dzykovic dzykovic added the ai:verified Declared behavior verified on the reported head label Oct 7, 2026
@dzykovic

dzykovic commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Code review - CLEAN

head: 8034dc5 - base: main - files 23, +142/-61

No Critical, Warning, or Suggestion findings.

Verified: ignore_file_has_line (cli/lib/gitignore.sh) is now the single presence test for ignore/include patterns, called from both the writer and status --check (cli/internal/check.sh:159,163); unit-gitignore.sh and the new e2e-negative CRLF scenario (both re-run here, plus once under real WSL/Linux grep semantics) pass; shellcheck at the project's --severity=warning gate is clean on every touched file; all version-lockstep files (engine/VERSION, every example's schema_version/pin, CHANGELOG.md) move together and match the already-published-0.18.1 -> pending-0.19.0 selection shared with open PR #54; the rule correction in intelligence/rules/shell.md points at the one shared implementation instead of restating it; commits are split one-logical-change-per-commit; no other grep-based presence check in cli/ reads a project file that can carry CRLF (the rest read CLI/engine-generated output or do substring, not exact-line, matching). PR body claims all have matching code in the diff, and nothing here contradicts the existing "Verification - PASS" comment on this head.

@dzykovic dzykovic added ai:reviewed Diff reviewed on the reported head ai:completed Agent work completed; required factors are fresh and removed ai:processing An agent is working on this pull request labels Oct 7, 2026
@dzykovic
dzykovic merged commit 18dd494 into main Oct 7, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:completed Agent work completed; required factors are fresh ai:reviewed Diff reviewed on the reported head ai:verified Declared behavior verified on the reported head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

status --check reports CRLF .gitignore patterns as missing on Linux and macOS

2 participants