@garrick0/c2-observable-git
v6.1.0
Published
C2 Git Observable - Git repository observer and checks
Readme
@garrick0/c2-observable-git
Git Observable Plugin for the C2 system. Provides git repository observation and checks.
Installation
npm install @garrick0/c2-observable-gitUsage
With the C2 CLI
The CLI includes this plugin by default. Just create a config file:
// c2.config.ts
import { defineUserConfig } from '@garrick0/c2';
export default defineUserConfig({
extends: ['c2:recommended'], // or 'git:recommended'
checks: {
'git:no-protected-branch': 'error',
},
});Programmatic Usage
import { run, defineUserConfig, createContextFromPlugins } from '@garrick0/c2';
import { createGitPlugin } from '@garrick0/c2-observable-git';
// User config (WHAT to check)
const userConfig = defineUserConfig({
extends: ['c2:recommended'],
});
// Host context (HOW to run)
const context = createContextFromPlugins([
createGitPlugin({
protectedBranches: ['main', 'master', 'develop'],
recentCommitCount: 10,
}),
]);
// Execute checks
const result = await run({ userConfig, context });
console.log(`${result.summary.passed}/${result.summary.total} checks passed`);Check Definitions (13 total)
Branching
| Check ID | Description | Default Severity |
|----------|-------------|------------------|
| git:no-protected-branch | Prevents working on protected branches | error |
| git:branch-naming | Enforces branch naming conventions | warning |
| git:not-detached-head | Warns about detached HEAD state | warning |
Hygiene
| Check ID | Description | Default Severity |
|----------|-------------|------------------|
| git:uncommitted-lines-limit | Warns about too many uncommitted lines | warning |
| git:clean-working-tree | Warns about uncommitted changes | warning |
| git:no-untracked-files | Warns about untracked files | warning |
Sync
| Check ID | Description | Default Severity |
|----------|-------------|------------------|
| git:up-to-date-with-remote | Warns when out of sync with remote | warning |
History
| Check ID | Description | Default Severity |
|----------|-------------|------------------|
| git:no-merge-commits | Encourages linear history | warning |
| git:commit-message-format | Enforces conventional commit format | warning |
| git:no-wip-commits | Warns about WIP commits | warning |
| git:no-lock-file-only-commits | Warns about lock-file-only commits | info |
Workflow
| Check ID | Description | Default Severity |
|----------|-------------|------------------|
| git:has-linear-issue | Ensures Linear issue reference | warning |
| git:has-valid-author | Ensures git author is configured | error |
Profiles
This plugin provides several built-in profiles:
git:recommended
Sensible defaults for most projects:
- Block working on protected branches (error)
- Warn about uncommitted changes
- Warn about WIP commits
git:strict
All checks enabled with error severity for CI/CD enforcement.
git:minimal
Only critical checks for permissive development:
- Block protected branches
- Ensure valid author
git:ci
Checks suited for CI environments:
- No WIP commits (error)
- Commit message format (error)
- No merge commits (warning)
Query Operations (14 total)
| Operation | Description |
|-----------|-------------|
| branchIsProtected | Check if current branch is protected |
| branchMatchesPattern | Check if branch matches naming pattern |
| hasUncommittedChanges | Check for uncommitted changes |
| uncommittedLinesBelow | Check if uncommitted lines below threshold |
| isClean | Check if working tree is clean |
| isUpToDateWithRemote | Check if branch is up to date with remote |
| hasNoUntrackedFiles | Check for untracked files |
| hasNoMergeCommits | Check for merge commits in history |
| commitMessagesMatch | Check if commit messages match pattern |
| noWipCommits | Check for WIP commits |
| hasLinearIssue | Check for Linear issue references |
| noLockFileOnlyCommits | Check for lock-file-only changes |
| hasValidAuthor | Check if git user is configured |
| notDetachedHead | Check if not in detached HEAD state |
Plugin Configuration
createGitPlugin({
// Custom git port adapter (for testing)
gitPort?: IGitPort;
// Default protected branches (default: ['main', 'master'])
protectedBranches?: string[];
// Number of recent commits to retrieve (default: 10)
recentCommitCount?: number;
});Architecture
This package uses the State + Port pattern for efficient git operations:
- GitState: Immutable snapshot of git repository state captured at observation time
- IGitPort: Interface for lazy loading additional data when queries need it
- Query Memoization: Caches query results to avoid redundant fetches
observable-git/
├── domain/
│ ├── GitState.ts # State type (v2 architecture)
│ ├── GitData.ts # Data types (CommitInfo)
│ ├── GitObservable.ts # Observable with async queries
│ ├── matchPattern.ts # Pattern matching utilities
│ └── queries/ # Query operations (14 files)
├── infrastructure/
│ ├── IGitPort.ts # Git port interface
│ ├── SimpleGitAdapter.ts # simple-git implementation
│ └── GitObserverAdapter.ts # Observer adapter
├── checks/
│ └── git-basic-checks.ts # Check definitions
└── register.ts # Plugin factory (createGitPlugin)GitState Structure
interface GitState {
// Core fields (always present)
currentBranch: string | null;
isDetached: boolean;
workingDirectory: string;
protectedBranches: string[];
isProtectedBranch: boolean;
// Eagerly loaded optional fields
status?: GitStatusData; // Changed/untracked files
diffStats?: DiffStats; // Line change statistics
recentCommits?: CommitInfo[]; // Recent commit history
remoteStatus?: GitRemoteData; // Remote sync status
hasMergeCommits?: boolean; // Merge commit detection
config?: GitConfigData; // Git user configuration
}Async Query API
All queries return Promise<QueryResponse>:
const observable = await observer.observe({ context: '/path/to/repo' });
const result = await observable.query({
operation: 'branchIsProtected'
});
// result: { ok: boolean, data: any, message?: string }API Reference
createGitPlugin(config?)
Create a C2 plugin descriptor for the git observable.
function createGitPlugin(config?: GitObservableConfig): C2PluginDescriptor;
interface GitObservableConfig {
gitPort?: IGitPort; // Custom git adapter
protectedBranches?: string[]; // Protected branch names
recentCommitCount?: number; // Commits to retrieve
}Exported Types
// Plugin API
export { createGitPlugin, GIT_PLUGIN_VERSION, GitObservableConfig };
// Profiles
export { gitProfiles, gitProfileRecommended, gitProfileStrict, gitProfileMinimal, gitProfileCI };
// Domain (v2)
export type { GitState, GitStatusData, GitRemoteData, GitConfigData };
export type { CommitInfo };
export { GitObservable, createGitState };
export { matchPattern, matchAnyPattern };
// Infrastructure (for advanced use / testing)
export { IGitPort, SimpleGitAdapter, GitObserverAdapter };
// Check definitions
export { gitCheckDefinitions };Development
# Build
npx nx build @garrick0/c2-observable-git
# Test
npx nx test @garrick0/c2-observable-git
# Lint
npx nx lint @garrick0/c2-observable-gitLicense
MIT
