Skip to content

feat: add write capability to TrailerService (GIT-66)#35

Merged
TonyCasey merged 3 commits intomainfrom
git-66
Feb 13, 2026
Merged

feat: add write capability to TrailerService (GIT-66)#35
TonyCasey merged 3 commits intomainfrom
git-66

Conversation

@TonyCasey
Copy link
Copy Markdown
Owner

@TonyCasey TonyCasey commented Feb 13, 2026

Summary

  • Adds addTrailers(trailers, cwd) method — amends HEAD commit to append AI-* trailers, deduplicating against existing trailers
  • Adds buildCommitMessage(message, trailers) method — pure string builder for composing commit messages with a trailer block
  • Detects existing trailer blocks (lines after last blank line matching Key: Value) to avoid double blank lines
  • 11 new tests covering both methods and edge cases

Depends on #34 (GIT-65)
Closes GIT-66

Test plan

  • npm run pre-commit passes (type-check + lint)
  • All 281 unit tests pass (11 new)
  • addTrailers amends HEAD correctly, preserves existing trailers, deduplicates
  • buildCommitMessage handles: no trailers, existing trailers, body text, trailing whitespace
  • Empty trailers array is a no-op (SHA unchanged)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Append trailers to commit messages with duplicate prevention and preservation of existing trailers; builds properly formatted commit messages.
  • Tests
    • Added extensive tests covering trailer formatting, message-building scenarios, and commit amend behavior to ensure reliability.

TonyCasey and others added 2 commits February 13, 2026 08:42
Wire the existing TrailerService into the awilix container as a
singleton so downstream issues can resolve it from the cradle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds two new methods:
- addTrailers: amends HEAD to append AI-* trailers, deduplicating
  against existing trailers on the commit
- buildCommitMessage: pure string builder for composing commit
  messages with a trailer block

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 13, 2026 08:46
@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.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

Introduces a TrailerService and adds two ITrailerService methods: addTrailers(trailers, cwd?) to amend HEAD with AI trailers (preserving existing and skipping duplicates) and buildCommitMessage(message, trailers) to produce a message string with appended trailers. Registers service in DI and adds unit tests.

Changes

Cohort / File(s) Summary
Interface
src/domain/interfaces/ITrailerService.ts
Added two method signatures: addTrailers(trailers: readonly ITrailer[], cwd?: string): void and buildCommitMessage(message: string, trailers: readonly ITrailer[]): string.
DI container / types
src/infrastructure/di/container.ts, src/infrastructure/di/types.ts
Imported and registered TrailerService as a singleton and exposed trailerService: ITrailerService on the container cradle.
Service implementation
src/infrastructure/services/TrailerService.ts
Implemented addTrailers() (reads existing trailers, filters duplicates, reads HEAD message, builds amended message, and amends HEAD) and buildCommitMessage() with a private hasTrailerBlock() helper to detect/append trailer blocks.
Tests
tests/unit/infrastructure/di/container.test.ts, tests/unit/infrastructure/services/TrailerService.test.ts
Added tests verifying DI exposure/singleton and comprehensive unit tests for buildCommitMessage() edge cases and addTrailers() behavior against a temporary git repo (preserve existing, avoid duplicates, add multiple, no-op on empty).

Sequence Diagram

sequenceDiagram
    participant Caller as Client
    participant TS as TrailerService
    participant Git as Git Repository

    Caller->>TS: addTrailers(newTrailers, cwd?)
    activate TS

    TS->>Git: query/read existing trailers (queryTrailers/readTrailers)
    Git-->>TS: existingTrailers

    TS->>TS: filterDuplicates(newTrailers, existingTrailers)
    TS->>Git: read HEAD commit message
    Git-->>TS: currentMessage

    TS->>TS: buildCommitMessage(currentMessage, filteredTrailers)
    TS->>TS: hasTrailerBlock(currentMessage)
    TS-->>TS: amendedMessage

    TS->>Git: amend HEAD with amendedMessage
    Git-->>TS: success

    deactivate TS
    TS-->>Caller: void
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add write capability to TrailerService' clearly and directly summarizes the main change—adding write functionality (addTrailers and buildCommitMessage methods) to the TrailerService.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch git-66

No actionable comments were generated in the recent review. 🎉


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

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds write support to the existing TrailerService so the tool can append AI-* trailers to the current commit, and introduces a pure helper for composing commit messages with trailer blocks. This builds on the DI registration work from GIT-65 and expands unit coverage around trailer handling.

Changes:

  • Add TrailerService.addTrailers() to amend HEAD and append (deduped) trailers.
  • Add TrailerService.buildCommitMessage() + trailer-block detection to avoid double blank lines.
  • Expand DI + unit tests for the new service capabilities.

Reviewed changes

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

Show a summary per file
File Description
src/infrastructure/services/TrailerService.ts Implements addTrailers and buildCommitMessage, plus trailer-block detection logic.
src/domain/interfaces/ITrailerService.ts Extends the domain interface with the new write and message-building methods.
src/infrastructure/di/types.ts Adds trailerService to the ICradle type.
src/infrastructure/di/container.ts Registers TrailerService in the Awilix container as a singleton.
tests/unit/infrastructure/services/TrailerService.test.ts Adds unit tests for buildCommitMessage and git-backed tests for addTrailers.
tests/unit/infrastructure/di/container.test.ts Extends container tests to cover trailerService resolution.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +98 to +101
// Read existing trailers to avoid duplicates
const existing = this.readTrailers('HEAD', cwd);
const existingKeys = new Set(existing.map(t => `${t.key}:${t.value}`));
const newTrailers = trailers.filter(t => !existingKeys.has(`${t.key}:${t.value}`));
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

addTrailers is documented as appending only AI-* trailers, but it currently accepts and appends any ITrailer keys. Since readTrailers() only returns AI-* trailers, passing non-AI trailers would bypass deduplication and can lead to duplicate non-AI trailers being appended on repeated calls. Consider filtering/validating inputs to AI_TRAILER_PREFIX (or isAiTrailer) and either ignoring or rejecting non-AI keys so behavior matches the docs and dedupe logic.

Suggested change
// Read existing trailers to avoid duplicates
const existing = this.readTrailers('HEAD', cwd);
const existingKeys = new Set(existing.map(t => `${t.key}:${t.value}`));
const newTrailers = trailers.filter(t => !existingKeys.has(`${t.key}:${t.value}`));
// Only operate on AI-* trailers to match readTrailers/parseTrailerBlock behavior.
const aiTrailers = trailers.filter(t => t.key.startsWith(AI_TRAILER_PREFIX));
if (aiTrailers.length === 0) return;
// Read existing trailers to avoid duplicates
const existing = this.readTrailers('HEAD', cwd);
const existingKeys = new Set(existing.map(t => `${t.key}:${t.value}`));
const newTrailers = aiTrailers.filter(
t => !existingKeys.has(`${t.key}:${t.value}`)
);

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed — added AI_TRAILER_PREFIX filter at the top of addTrailers so non-AI trailers are rejected before deduplication. See 8fcd93f.


assert.equal(typeof trailerService.readTrailers, 'function');
assert.equal(typeof trailerService.formatTrailers, 'function');
assert.equal(typeof trailerService.queryTrailers, 'function');
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

This test block claims to check the resolved TrailerService interface, but it only asserts the pre-existing methods. Since ITrailerService now includes addTrailers and buildCommitMessage, either add assertions for those methods too or rename the test to avoid going stale/misleading.

Suggested change
assert.equal(typeof trailerService.queryTrailers, 'function');
assert.equal(typeof trailerService.queryTrailers, 'function');
assert.equal(typeof trailerService.addTrailers, 'function');
assert.equal(typeof trailerService.buildCommitMessage, 'function');

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed — added assertions for addTrailers and buildCommitMessage to the container interface test. See 8fcd93f.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@tests/unit/infrastructure/di/container.test.ts`:
- Around line 166-179: Update the DI unit test for trailerService to assert the
new methods on the resolved service: verify that container.cradle.trailerService
exposes addTrailers and buildCommitMessage as functions in the same style as
existing assertions for readTrailers, formatTrailers, and queryTrailers; keep
the existing singleton test unchanged so it still confirms
container.cradle.trailerService === container.cradle.trailerService.

- Filter addTrailers input to AI-* prefixed trailers only
- Add addTrailers and buildCommitMessage to container interface test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@TonyCasey TonyCasey merged commit d4513dd into main Feb 13, 2026
3 checks passed
@TonyCasey TonyCasey deleted the git-66 branch February 13, 2026 11:36
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