Skip to content

Add GitIgnoreEnsurer to proactively protect managed agent folders - #7

Merged
Malcolmnixon merged 5 commits into
mainfrom
feature/gitignore-ensure-agent-folders
Sep 10, 2026
Merged

Add GitIgnoreEnsurer to proactively protect managed agent folders#7
Malcolmnixon merged 5 commits into
mainfrom
feature/gitignore-ensure-agent-folders

Conversation

@Malcolmnixon

Copy link
Copy Markdown
Member

Summary

Adds a new GitIgnoreEnsurer unit (RepoSync subsystem) that proactively protects a repo's .gitignore so the four managed agent-package folders (.github/agents, .github/standards, .github/templates, .github/skills) can't be accidentally committed by an agentic coding tool before AgentControl's existing advisory badge would ever catch it.

Problem

The existing "Committed agent files" badge only detects the problem after files are already committed - too late if an agentic tool has already run git add/git commit on a developer's behalf. The fix needs to happen at the moment the folders are created on disk (package extraction), before any commit can occur.

Change

  • New static unit GitIgnoreEnsurer: scans the repo-root .gitignore for a fixed marker comment (# Added by AgentControl - agent package folders). If absent, appends a block covering the four managed folders (creating the file if missing). Purely additive - never edits/removes existing lines; no git check-ignore call and no gitignore glob-pattern analysis (marker presence is the sole idempotency gate, an intentional simplicity-over-precision tradeoff).
  • Wired into RepoCardViewModel immediately after every successful PackageZipExtractor.Extract call, in both the "Select Package..." and "Upgrade" flows, wrapped in its own non-blocking try/catch so .gitignore I/O failures never abort extraction or the pin-file write.
  • The existing "Committed agent files" advisory badge is unchanged - this is additive, not a replacement.
  • Companion artifacts: unit + wiring tests, sysml2 model, design docs, verification docs, reqstream requirements, .reviewmark.yaml entry, and documentation updates (architecture.md, docs/user_guide/introduction.md, README.md).

Validation

  • pwsh ./fix.ps1 / pwsh ./build.ps1: build succeeded, 199/199 tests passing.
  • pwsh ./lint.ps1: passes cleanly (yamllint, cspell, markdownlint-cli2, reqstream, versionmark, reviewmark, sysml2tools, dotnet format --verify-no-changes).
  • Built-in code-review agent (gpt-5.4-mini): no significant issues.
  • Formal review of AgentControl-LauncherUI-RepoCardViewModel review-set: Pass, 0 findings.
  • Formal review of AgentControl-RepoSync-GitIgnoreEnsurer review-set: one flagged item (missing SysML2 path in review-set) verified as a false positive - matches the existing convention used by the sibling ReleaseNotesViewerViewModel review-set.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Adds a new GitIgnoreEnsurer unit (RepoSync subsystem) that ensures a repo's
.gitignore covers the four managed agent-package folders (.github/agents,
.github/standards, .github/templates, .github/skills) immediately after a
successful package extraction, before any commit can occur.

- Idempotency is a marker-comment scan only (no git check-ignore, no glob
  analysis) - purely additive, never edits/removes existing .gitignore lines.
- Wired into RepoCardViewModel right after PackageZipExtractor.Extract in
  both the "Select Package..." and "Upgrade" flows, wrapped in a non-blocking
  try/catch so I/O failures never abort extraction.
- Complements (does not replace) the existing advisory "Committed agent
  files" badge, which remains unchanged.
- Adds companion tests, design/verification docs, reqstream requirements,
  and SysML2 model updates for the new unit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 9, 2026 21:36

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.

🟢 Approval recommended

The change is additive, well-covered by tests and companion artifacts, and introduces no blocking correctness or safety issues.

Pull request overview

This PR adds a proactive .gitignore protection step to the RepoSync flow so the four managed agent-package folders (.github/agents, .github/standards, .github/templates, .github/skills) are less likely to be accidentally committed immediately after extraction.

Changes:

  • Introduces GitIgnoreEnsurer (RepoSync) to append a marker-delimited .gitignore block for the managed folders (additive-only, marker-scan idempotency).
  • Wires .gitignore ensuring into RepoCardViewModel right after successful package extraction (non-blocking warning on failure).
  • Adds unit tests and updates requirements, SysML2 model, design/verification docs, and review metadata to cover the new unit and behavior.
File summaries
File Description
test/DemaConsulting.AgentControl.Tests/RepoSync/GitIgnoreEnsurerTests.cs Adds unit tests for marker-scan idempotency, file creation/appending, and I/O failure wrapping.
test/DemaConsulting.AgentControl.Tests/LauncherUI/RepoCardViewModelTests.cs Adds coverage ensuring .gitignore is updated after Upgrade/Select Package, and that .gitignore failures are non-blocking.
src/DemaConsulting.AgentControl/RepoSync/GitIgnoreEnsurer.cs Implements additive .gitignore update with marker-based idempotency and I/O exception wrapping.
src/DemaConsulting.AgentControl/LauncherUI/RepoCardViewModel.cs Calls GitIgnoreEnsurer after extraction via a dedicated non-blocking wrapper.
requirements.yaml Includes the new GitIgnoreEnsurer requirements file in the root requirements set.
README.md Documents the new proactive .gitignore protection alongside existing badges/behavior.
docs/verification/agent-control/repo-sync/git-ignore-ensurer.md Adds unit-level verification design for GitIgnoreEnsurer and its acceptance criteria.
docs/verification/agent-control/repo-sync.md Updates RepoSync verification approach/criteria to include .gitignore prevention behavior and tests.
docs/user_guide/introduction.md Updates user guide to describe proactive .gitignore ensuring in Select Package/Upgrade flows.
docs/sysml2/model/agent-control/repo-sync/git-ignore-ensurer.sysml Adds SysML2 element tying source/test/design/verification/requirements for GitIgnoreEnsurer.
docs/sysml2/model/agent-control/repo-sync.sysml Updates RepoSync model to include GitIgnoreEnsurer as a subsystem part and describe behavior.
docs/reqstream/agent-control/repo-sync/git-ignore-ensurer.yaml Adds unit requirements for marker-based additive .gitignore enforcement.
docs/reqstream/agent-control/repo-sync.yaml Adds subsystem-level requirement for post-sync .gitignore coverage and links to unit requirement/tests.
docs/design/agent-control/repo-sync/git-ignore-ensurer.md Adds design doc describing purpose, data model, behavior, error handling, and callers.
docs/design/agent-control/repo-sync.md Updates subsystem design to include GitIgnoreEnsurer interface/contract and rationale for placement.
docs/design/agent-control/launcher-ui/repo-card-view-model.md Documents the new non-blocking ensure step in the shared extract-and-pin sequence and error handling.
architecture.md Notes the new proactive .gitignore ensure step as additive to the advisory committed-files badge.
.reviewmark.yaml Adds a ReviewMark review-set for the new GitIgnoreEnsurer unit and companion artifacts.
.cspell.yaml Adds “unreordered” to the repository dictionary to support new documentation/test wording.
Review details
  • Files reviewed: 19/19 changed files
  • Comments generated: 2
  • Review effort level: Lite

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

Comment thread src/DemaConsulting.AgentControl/RepoSync/GitIgnoreEnsurer.cs Outdated
Comment thread src/DemaConsulting.AgentControl/LauncherUI/RepoCardViewModel.cs
…ped error message

- GitIgnoreEnsurer now detects and reuses the existing .gitignore file's
  newline style (CRLF vs LF) instead of always using Environment.NewLine,
  avoiding mixed line endings when appending on a different OS than the
  file was originally created on.
- RepoCardViewModel.EnsureGitIgnoreCoversManagedFolders now surfaces
  GitIgnoreEnsurer's exception message directly instead of re-wrapping it
  with a redundant "Failed to update .gitignore..." prefix.
- Updated GitIgnoreEnsurerTests to assert the new newline-preservation
  behavior for LF-only existing content.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 9, 2026 21:55

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.

🟡 Changes recommended

GitIgnoreEnsurer rewrites .gitignore with WriteAllText, which can change a user-owned file’s original encoding/BOM despite the “purely additive” intent.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 19/19 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src/DemaConsulting.AgentControl/RepoSync/GitIgnoreEnsurer.cs Outdated
- GitIgnoreEnsurer now detects and preserves the existing .gitignore file's
  encoding (including a UTF-8 BOM if present) when rewriting it, instead of
  always writing back as UTF-8 without a BOM - a user-owned file should not
  have its encoding silently changed by a purely additive update. New files
  default to UTF-8 without a BOM.
- Added GitIgnoreEnsurerTests coverage for CRLF-only existing content
  (protecting DetectNewLine/BuildSeparator from Windows-created .gitignore
  regressions) and for UTF-8 BOM preservation on rewrite.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 9, 2026 22:08

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.

🟡 Changes recommended

GitIgnoreEnsurer currently overwrites .gitignore in-place (risking corruption on mid-write failures) and contains a couple of inaccurate documentation claims that should be corrected.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

src/DemaConsulting.AgentControl/RepoSync/GitIgnoreEnsurer.cs:41

  • The remarks claim this class is "thread-safe", but Ensure does an unsynchronized read-modify-write of a shared file. Concurrent calls can race and write duplicate blocks, so the doc is currently incorrect (and could hide a real concurrency edge case).

This issue also appears on line 113 of the same file.

src/DemaConsulting.AgentControl/RepoSync/GitIgnoreEnsurer.cs:116

  • ReadExistingFile only preserves encodings that can be detected via a BOM (because the StreamReader is constructed with UTF-8 + BOM detection). The current doc mentions preserving "non-UTF8 encoding" generally, which isn't accurate for non-BOM legacy encodings.
    ///     <see cref="Ensure"/> can write the updated content back using the same encoding the
    ///     file already had (preserving a BOM/non-UTF8 encoding rather than silently normalizing
    ///     it to UTF-8) - a user-owned file should not have its encoding changed as a side effect
    ///     of a purely additive update.
  • Files reviewed: 19/19 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/DemaConsulting.AgentControl/RepoSync/GitIgnoreEnsurer.cs
…racy, reqstream orphan fix

- Write .gitignore atomically (temp file + File.Replace/File.Move) so a
  mid-write failure (disk full, crash) can never leave a truncated or
  corrupted .gitignore behind.
- Correct XML doc comments: remove inaccurate 'thread-safe' claim (Ensure
  performs an unsynchronized read-modify-write) and clarify that only
  BOM-detectable encodings are preserved, not non-UTF8 encodings generally.
- Fix orphaned-requirements reqstream lint error by linking
  AgentControl-RepoSync-GitIgnorePrevention into AgentControl-System-Upgrade's
  children.
- Update design/verification docs and reqstream test lists accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 9, 2026 23:46

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.

🟡 Changes recommended

The documentation includes a concrete inaccuracy about Ensure “never” throwing (it can still throw on read I/O failures), and there is also a small punctuation fix needed in the user guide.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

docs/user_guide/introduction.md:66

  • This bullet ends without a period, which makes the sentence grammatically incomplete compared to the surrounding documentation text.
  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread docs/design/agent-control/repo-sync/git-ignore-ensurer.md Outdated
- Correct git-ignore-ensurer.md: the marker-already-present no-op path
  still performs an initial read and can still throw InvalidOperationException
  if that read fails; it simply never writes.
- Add missing period to a user guide bullet.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 10, 2026 00:28

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.

🟢 Approval recommended

The implementation is narrowly scoped, consistent with the stated design/requirements, and is backed by targeted unit tests plus updated companion documentation/model artifacts.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@Malcolmnixon
Malcolmnixon merged commit 291a321 into main Sep 10, 2026
8 checks passed
@Malcolmnixon
Malcolmnixon deleted the feature/gitignore-ensure-agent-folders branch September 10, 2026 00:47
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.

2 participants