@gitgov/core 1.13.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1369 @@
1
+ import { R as RecordStore, C as ConfigStore, G as GitGovConfig, S as SessionStore, a as GitGovSession, I as IGitModule, b as GitModuleDependencies, E as ExecOptions, c as ExecResult, d as ChangedFile, e as GetCommitHistoryOptions, f as CommitInfo, g as CommitAuthor } from './index--ahcnsG3.js';
2
+ export { F as FsFileListerOptions } from './index--ahcnsG3.js';
3
+ import { C as ConfigManager, S as SessionManager, I as ILintModule, L as LintOptions, a as LintReport, F as FixRecordOptions, b as FixReport, R as RecordStores, c as IIndexerAdapter, G as GitGovRecord, d as LintRecordContext, e as LintResult, f as IProjectInitializer, E as EnvironmentValidation, g as ISyncStateModule, h as SyncStateModuleDependencies, i as StateDeltaFile, j as ConflictDiff, k as IntegrityViolation, A as AuditStateOptions, l as AuditStateReport, m as SyncStatePushOptions, n as SyncStatePushResult, o as SyncStatePullOptions, p as SyncStatePullResult, q as SyncStateResolveOptions, r as SyncStateResolveResult, s as IEventStream, t as IAgentRunner, P as ProtocolHandlerRegistry, u as AgentRunnerDependencies, v as RunOptions, w as AgentResponse } from './agent_runner-ByOUWOt6.js';
4
+ export { z as FsFileLister, x as FsKeyProvider, y as FsKeyProviderOptions } from './agent_runner-ByOUWOt6.js';
5
+
6
+ /**
7
+ * Serializer for FsRecordStore - allows custom serialization
8
+ */
9
+ interface Serializer {
10
+ stringify: (value: unknown) => string;
11
+ parse: <T>(text: string) => T;
12
+ }
13
+ /**
14
+ * IdEncoder for transforming IDs to filesystem-safe filenames
15
+ * Useful for characters not allowed in filesystem (e.g., `:` on Windows)
16
+ */
17
+ interface IdEncoder {
18
+ /** Transform ID to filename-safe string */
19
+ encode: (id: string) => string;
20
+ /** Recover original ID from filename */
21
+ decode: (encoded: string) => string;
22
+ }
23
+ /**
24
+ * Default encoder: `:` → `_` (for IDs like "human:camilo")
25
+ * Reversible because IDs cannot contain `_` (see id_generator.ts)
26
+ */
27
+ declare const DEFAULT_ID_ENCODER: IdEncoder;
28
+ /**
29
+ * Options for FsRecordStore
30
+ */
31
+ interface FsRecordStoreOptions {
32
+ /** Base directory for files */
33
+ basePath: string;
34
+ /** File extension (default: ".json") */
35
+ extension?: string;
36
+ /** Custom serializer (default: JSON with indent 2) */
37
+ serializer?: Serializer;
38
+ /** Create directory if it doesn't exist (default: true) */
39
+ createIfMissing?: boolean;
40
+ /** ID encoder for filesystem-safe filenames (default: undefined = no encoding) */
41
+ idEncoder?: IdEncoder;
42
+ }
43
+ /**
44
+ * FsRecordStore<T> - Filesystem implementation of Store<T>
45
+ *
46
+ * Persists records as JSON files on disk.
47
+ *
48
+ * @example
49
+ * const store = new FsRecordStore<TaskRecord>({
50
+ * basePath: '.gitgov/tasks',
51
+ * });
52
+ *
53
+ * await store.put('123-task-foo', task);
54
+ * const task = await store.get('123-task-foo');
55
+ */
56
+ declare class FsRecordStore<T> implements RecordStore<T> {
57
+ private readonly basePath;
58
+ private readonly extension;
59
+ private readonly serializer;
60
+ private readonly createIfMissing;
61
+ private readonly idEncoder;
62
+ constructor(options: FsRecordStoreOptions);
63
+ private getFilePath;
64
+ get(id: string): Promise<T | null>;
65
+ put(id: string, value: T): Promise<void>;
66
+ delete(id: string): Promise<void>;
67
+ list(): Promise<string[]>;
68
+ exists(id: string): Promise<boolean>;
69
+ }
70
+
71
+ /**
72
+ * FsConfigStore - Filesystem implementation of ConfigStore
73
+ *
74
+ * Handles persistence of config.json to the local filesystem.
75
+ *
76
+ * NOTE: Session state (.session.json) is handled by FsSessionStore.
77
+ * NOTE: Project discovery utilities are in src/utils/project_discovery.ts
78
+ */
79
+
80
+ /**
81
+ * Filesystem-based ConfigStore implementation.
82
+ *
83
+ * Stores configuration in .gitgov/config.json.
84
+ * Implements fail-safe pattern: returns null instead of throwing for missing files.
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const store = new FsConfigStore('/path/to/project');
89
+ * const config = await store.loadConfig();
90
+ * if (config) {
91
+ * console.log(config.projectName);
92
+ * }
93
+ * ```
94
+ */
95
+ declare class FsConfigStore implements ConfigStore {
96
+ private readonly configPath;
97
+ constructor(projectRootPath: string);
98
+ /**
99
+ * Load project configuration from .gitgov/config.json
100
+ *
101
+ * [EARS-A1] Returns complete GitGovConfig for valid files
102
+ * [EARS-A2] Returns null for non-existent files (fail-safe)
103
+ * [EARS-A3] Returns null for invalid JSON (graceful degradation)
104
+ */
105
+ loadConfig(): Promise<GitGovConfig | null>;
106
+ /**
107
+ * Save project configuration to .gitgov/config.json
108
+ *
109
+ * [EARS-A4] Writes config with JSON indentation
110
+ */
111
+ saveConfig(config: GitGovConfig): Promise<void>;
112
+ }
113
+ /**
114
+ * Create a ConfigManager instance for a project.
115
+ *
116
+ * [EARS-B1] Factory function that creates a ConfigManager with FsConfigStore backend.
117
+ * Use this when you already have the projectRoot (e.g., from DI container).
118
+ *
119
+ * @param projectRoot - Absolute path to project root (REQUIRED)
120
+ * @returns ConfigManager instance with FsConfigStore backend
121
+ */
122
+ declare function createConfigManager(projectRoot: string): ConfigManager;
123
+
124
+ /**
125
+ * FsSessionStore - Filesystem implementation of SessionStore
126
+ *
127
+ * Handles persistence of .session.json to the local filesystem.
128
+ * Session files are machine-local and NOT versioned in Git.
129
+ */
130
+
131
+ /**
132
+ * Filesystem-based SessionStore implementation.
133
+ *
134
+ * Stores session state in .gitgov/.session.json.
135
+ * Implements fail-safe pattern: returns null instead of throwing for missing files.
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const store = new FsSessionStore('/path/to/project');
140
+ * const session = await store.loadSession();
141
+ * if (session) {
142
+ * console.log(session.lastSession?.actorId);
143
+ * }
144
+ * ```
145
+ */
146
+ declare class FsSessionStore implements SessionStore {
147
+ private readonly sessionPath;
148
+ private readonly actorsPath;
149
+ constructor(projectRootPath: string);
150
+ /**
151
+ * Load local session from .gitgov/.session.json
152
+ *
153
+ * [EARS-A1] Returns complete GitGovSession for valid files
154
+ * [EARS-A2] Returns null for non-existent files (fail-safe)
155
+ * [EARS-A3] Returns null for invalid JSON (graceful degradation)
156
+ * [EARS-A4] Returns cloud token if present
157
+ * [EARS-A5] Returns syncPreferences if present
158
+ */
159
+ loadSession(): Promise<GitGovSession | null>;
160
+ /**
161
+ * Save local session to .gitgov/.session.json
162
+ *
163
+ * [EARS-B1] Writes session to .gitgov/.session.json with JSON indentation
164
+ * [EARS-B2] Preserves all fields (cloud, actorState, syncPreferences)
165
+ */
166
+ saveSession(session: GitGovSession): Promise<void>;
167
+ /**
168
+ * Detect actor from .key files in .gitgov/actors/
169
+ *
170
+ * [EARS-C1] Returns actor ID from first .key file
171
+ * [EARS-C2] Returns first .key file alphabetically if multiple exist
172
+ * [EARS-C3] Returns null if no .key files exist
173
+ * [EARS-C4] Returns null if actors directory doesn't exist
174
+ * [EARS-C5] Ignores non-.key files
175
+ * [EARS-C6] Returns null for empty directory
176
+ *
177
+ * @returns Actor ID (e.g., "human:camilo-v2") or null
178
+ */
179
+ detectActorFromKeyFiles(): Promise<string | null>;
180
+ }
181
+ /**
182
+ * Create a SessionManager instance for a project.
183
+ *
184
+ * [EARS-D1] Factory function that creates a SessionManager with FsSessionStore backend.
185
+ * Use this when you already have the projectRoot (e.g., from DI container).
186
+ *
187
+ * @param projectRoot - Absolute path to project root (REQUIRED)
188
+ * @returns SessionManager instance with FsSessionStore backend
189
+ */
190
+ declare function createSessionManager(projectRoot: string): SessionManager;
191
+
192
+ /**
193
+ * Filesystem-specific types for FsLintModule.
194
+ *
195
+ * These types are exported via @gitgov/core/fs subpath.
196
+ * For pure validation types, use @gitgov/core.
197
+ */
198
+
199
+ /**
200
+ * Public interface for FsLintModule operations (with I/O).
201
+ *
202
+ * This interface wraps LintModule and adds filesystem operations:
203
+ * - Directory scanning for record discovery
204
+ * - File reading and parsing
205
+ * - Backup creation and restoration
206
+ * - File writing for fixes
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const fsLintModule: IFsLintModule = new FsLintModule({
211
+ * lintModule,
212
+ * stores
213
+ * });
214
+ *
215
+ * // Scan directory and validate all records
216
+ * const report = await fsLintModule.lint({ path: '.gitgov/' });
217
+ *
218
+ * // Validate specific file
219
+ * const fileReport = await fsLintModule.lintFile(filePath);
220
+ *
221
+ * // Fix with backups
222
+ * const fixReport = await fsLintModule.fix(report, { createBackups: true });
223
+ * ```
224
+ */
225
+ interface IFsLintModule extends ILintModule {
226
+ /**
227
+ * Scans directories and validates all records.
228
+ * Overrides ILintModule.lint() to accept filesystem-specific options.
229
+ */
230
+ lint(options?: Partial<FsLintOptions>): Promise<LintReport>;
231
+ /**
232
+ * Validates a specific file.
233
+ */
234
+ lintFile(filePath: string, options?: Partial<FsLintOptions>): Promise<LintReport>;
235
+ /**
236
+ * Applies automatic repairs to files, creating backups.
237
+ */
238
+ fix(lintReport: LintReport, fixOptions?: Partial<FsFixOptions>): Promise<FixReport>;
239
+ }
240
+ /**
241
+ * Dependencies for FsLintModule.
242
+ */
243
+ interface FsLintModuleDependencies {
244
+ /** Absolute path to project root (REQUIRED, injected from DI/CLI bootstrap) */
245
+ projectRoot: string;
246
+ /** Core LintModule for pure validation (REQUIRED) */
247
+ lintModule: ILintModule;
248
+ /** Record stores for reference lookups (OPTIONAL) */
249
+ stores?: RecordStores;
250
+ /** Indexer adapter for reference resolution (OPTIONAL) */
251
+ indexerAdapter?: IIndexerAdapter;
252
+ /** FileSystem abstraction for I/O (OPTIONAL, default: Node.js fs) */
253
+ fileSystem?: FileSystem;
254
+ }
255
+ /**
256
+ * Options for FsLintModule operations.
257
+ * Extends LintOptions with filesystem-specific settings.
258
+ */
259
+ interface FsLintOptions extends LintOptions {
260
+ /** Directory or file to validate (default: '.gitgov/') */
261
+ path?: string;
262
+ /** Validate file naming conventions (default: true) */
263
+ validateFileNaming?: boolean;
264
+ }
265
+ /**
266
+ * Options for FsLintModule fix operation.
267
+ * Extends FixRecordOptions with filesystem-specific settings.
268
+ */
269
+ interface FsFixOptions extends FixRecordOptions {
270
+ /** Create backups before modifying files (default: true) */
271
+ createBackups?: boolean;
272
+ /** Dry-run mode that reports without applying changes (default: false) */
273
+ dryRun?: boolean;
274
+ }
275
+ /**
276
+ * FileSystem interface for I/O operations.
277
+ * Can be mocked for testing.
278
+ */
279
+ interface FileSystem {
280
+ readFile(path: string, encoding: string): Promise<string>;
281
+ writeFile(path: string, content: string): Promise<void>;
282
+ exists(path: string): Promise<boolean>;
283
+ unlink(path: string): Promise<void>;
284
+ readdir?(path: string): Promise<string[]>;
285
+ }
286
+
287
+ /**
288
+ * FsLintModule - Filesystem-aware Validation
289
+ *
290
+ * This module wraps the pure LintModule and adds filesystem operations:
291
+ * - Directory scanning for record discovery (EARS-A1)
292
+ * - File naming validation (EARS-B1, EARS-B2)
293
+ * - Backup creation and restoration (EARS-C1, EARS-C2)
294
+ * - Delegation to LintModule core (EARS-D1)
295
+ * - Schema version detection (EARS-E1)
296
+ * - Error filtering (EARS-F1)
297
+ *
298
+ * @see fs_lint_module.md for EARS specifications
299
+ * @module lint/fs
300
+ */
301
+
302
+ /**
303
+ * Filesystem-aware lint module.
304
+ * Wraps LintModule (pure) and adds I/O operations.
305
+ *
306
+ * @implements {IFsLintModule}
307
+ */
308
+ declare class FsLintModule implements IFsLintModule {
309
+ private readonly projectRoot;
310
+ private readonly lintModule;
311
+ private readonly fileSystem;
312
+ private lastBackupPath;
313
+ /**
314
+ * Constructor for FsLintModule.
315
+ *
316
+ * @param dependencies - Module dependencies
317
+ */
318
+ constructor(dependencies: FsLintModuleDependencies);
319
+ /**
320
+ * Delegates to LintModule.lintRecord() for pure validation.
321
+ */
322
+ lintRecord(record: GitGovRecord, context: LintRecordContext): LintResult[];
323
+ /**
324
+ * Delegates to LintModule.fixRecord() for pure fix.
325
+ */
326
+ fixRecord(record: GitGovRecord, results: LintResult[], options: FixRecordOptions): GitGovRecord;
327
+ /**
328
+ * [EARS-A1] Scans directories and validates all records.
329
+ *
330
+ * @param options - Configuration options
331
+ * @returns Consolidated lint report
332
+ */
333
+ lint(options?: Partial<FsLintOptions>): Promise<LintReport>;
334
+ /**
335
+ * Validates a specific file.
336
+ *
337
+ * @param filePath - Path to the file to validate
338
+ * @param options - Configuration options
339
+ * @returns Lint report for this single file
340
+ */
341
+ lintFile(filePath: string, options?: Partial<FsLintOptions>): Promise<LintReport>;
342
+ /**
343
+ * Applies automatic repairs to files, creating backups.
344
+ *
345
+ * @param lintReport - Lint report with detected problems
346
+ * @param fixOptions - Options for the fix operation
347
+ * @returns Report of applied repairs
348
+ */
349
+ fix(lintReport: LintReport, fixOptions?: Partial<FsFixOptions>): Promise<FixReport>;
350
+ /**
351
+ * Validates a single record by reading from filesystem.
352
+ * @private
353
+ */
354
+ private lintSingleRecord;
355
+ /**
356
+ * [EARS-B1, EARS-B2] Validates file naming conventions.
357
+ * @private
358
+ */
359
+ private validateFileNaming;
360
+ /**
361
+ * [EARS-A1] Discovers all records with their types by scanning filesystem.
362
+ * @private
363
+ */
364
+ private discoverAllRecordsWithTypes;
365
+ /**
366
+ * Gets file path for a record.
367
+ * @private
368
+ */
369
+ private getFilePath;
370
+ /**
371
+ * [EARS-C1] Creates a backup of a file before modification.
372
+ * @private
373
+ */
374
+ private createBackup;
375
+ /**
376
+ * [EARS-C2] Restores file from backup if fix fails.
377
+ * @private
378
+ */
379
+ private restoreBackup;
380
+ /**
381
+ * Applies a fix to a file.
382
+ * @private
383
+ */
384
+ private applyFix;
385
+ /**
386
+ * Fixes legacy record with embedded metadata issues.
387
+ * @private
388
+ */
389
+ private fixLegacyRecord;
390
+ /**
391
+ * Fixes bidirectional reference inconsistencies.
392
+ * @private
393
+ */
394
+ private fixBidirectionalReference;
395
+ /**
396
+ * Recalculates checksum for a record.
397
+ * @private
398
+ */
399
+ private recalculateChecksum;
400
+ /**
401
+ * Fixes signature structure issues.
402
+ * @private
403
+ */
404
+ private fixSignatureStructure;
405
+ /**
406
+ * [EARS-E1] Detects validator type from error message.
407
+ * Includes detection of SCHEMA_VERSION_MISMATCH for outdated schemas.
408
+ * @private
409
+ */
410
+ private detectValidatorType;
411
+ /**
412
+ * Determines if an error is fixable.
413
+ * @private
414
+ */
415
+ private isFixable;
416
+ }
417
+
418
+ /**
419
+ * FsProjectInitializer - Filesystem implementation of IProjectInitializer.
420
+ *
421
+ * Initializes GitGovernance projects on the local filesystem,
422
+ * creating the .gitgov/ directory structure and configuration files.
423
+ *
424
+ * The projectRoot is injected at construction time (DI from CLI/bootstrap).
425
+ *
426
+ * @example
427
+ * ```typescript
428
+ * const initializer = new FsProjectInitializer('/path/to/project');
429
+ *
430
+ * const validation = await initializer.validateEnvironment();
431
+ * if (!validation.isValid) {
432
+ * console.log(validation.warnings);
433
+ * return;
434
+ * }
435
+ *
436
+ * await initializer.createProjectStructure();
437
+ * await initializer.writeConfig(config);
438
+ * await initializer.initializeSession(actorId);
439
+ * await initializer.copyAgentPrompt();
440
+ * await initializer.setupGitIntegration();
441
+ * ```
442
+ */
443
+ declare class FsProjectInitializer implements IProjectInitializer {
444
+ private readonly projectRoot;
445
+ constructor(projectRoot: string);
446
+ /**
447
+ * Creates the .gitgov/ directory structure.
448
+ */
449
+ createProjectStructure(): Promise<void>;
450
+ /**
451
+ * Checks if .gitgov/config.json exists.
452
+ */
453
+ isInitialized(): Promise<boolean>;
454
+ /**
455
+ * Writes config.json to .gitgov/
456
+ */
457
+ writeConfig(config: GitGovConfig): Promise<void>;
458
+ /**
459
+ * Creates .session.json with initial actor state.
460
+ */
461
+ initializeSession(actorId: string): Promise<void>;
462
+ /**
463
+ * Reads a file from the filesystem.
464
+ */
465
+ readFile(filePath: string): Promise<string>;
466
+ /**
467
+ * Gets the path for an actor record.
468
+ */
469
+ getActorPath(actorId: string): string;
470
+ /**
471
+ * Validates environment for GitGovernance initialization.
472
+ * Checks: Git repo exists, write permissions, not already initialized.
473
+ */
474
+ validateEnvironment(): Promise<EnvironmentValidation>;
475
+ /**
476
+ * Copies the @gitgov agent prompt to project root for IDE access.
477
+ */
478
+ copyAgentPrompt(): Promise<void>;
479
+ /**
480
+ * Sets up .gitignore for GitGovernance files.
481
+ */
482
+ setupGitIntegration(): Promise<void>;
483
+ /**
484
+ * Removes .gitgov/ directory (for rollback on failed init).
485
+ */
486
+ rollback(): Promise<void>;
487
+ }
488
+
489
+ /**
490
+ * LocalGitModule - Local Git Operations via CLI
491
+ *
492
+ * This module provides a business-agnostic abstraction layer for interacting
493
+ * with the local Git repository. It exposes semantic methods instead of raw
494
+ * Git commands, with comprehensive error handling and type safety.
495
+ *
496
+ * Uses execCommand (injected) to run git CLI commands.
497
+ *
498
+ * @module git/local
499
+ */
500
+
501
+ /**
502
+ * LocalGitModule - CLI-based implementation of IGitModule
503
+ *
504
+ * All operations are async and use dependency injection for testability.
505
+ * Errors are transformed into typed exceptions for better handling.
506
+ *
507
+ * For unit tests without git, use MemoryGitModule instead.
508
+ */
509
+ declare class LocalGitModule implements IGitModule {
510
+ private repoRoot;
511
+ private execCommand;
512
+ /**
513
+ * Creates a new LocalGitModule instance
514
+ *
515
+ * @param dependencies - Required dependencies (execCommand) and optional config (repoRoot)
516
+ * @throws Error if execCommand is not provided
517
+ */
518
+ constructor(dependencies: GitModuleDependencies);
519
+ /**
520
+ * Ensures that repoRoot is set, auto-detecting it if necessary
521
+ *
522
+ * @returns Path to repository root
523
+ * @throws GitCommandError if not in a Git repository
524
+ */
525
+ private ensureRepoRoot;
526
+ /**
527
+ * Executes a Git command with standardized error handling
528
+ *
529
+ * @param args - Git command arguments
530
+ * @param options - Execution options
531
+ * @returns Command result
532
+ * @throws GitCommandError if command fails
533
+ */
534
+ private execGit;
535
+ /**
536
+ * Executes an arbitrary shell command with the repository as working directory.
537
+ *
538
+ * This method is intended for advanced use cases where the existing
539
+ * semantic methods don't cover the needed functionality. Use with caution.
540
+ *
541
+ * @param command - The command to execute (e.g., 'git')
542
+ * @param args - Command arguments
543
+ * @param options - Optional execution options
544
+ * @returns Command execution result with exitCode, stdout, stderr
545
+ *
546
+ * @example
547
+ * const result = await gitModule.exec('git', ['diff', '--name-only', 'HEAD~1..HEAD']);
548
+ * if (result.exitCode === 0) {
549
+ * const files = result.stdout.split('\n');
550
+ * }
551
+ */
552
+ exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
553
+ /**
554
+ * Initializes a new Git repository in the current directory
555
+ *
556
+ * Creates the `.git/` directory structure and sets up initial configuration.
557
+ * Useful for testing and for commands that require a fresh repository.
558
+ *
559
+ * @throws GitCommandError if directory is already a Git repository
560
+ *
561
+ * @example
562
+ * await gitModule.init();
563
+ * // Repository initialized with default branch (main or master)
564
+ */
565
+ init(): Promise<void>;
566
+ /**
567
+ * Returns the absolute path to the current Git repository root
568
+ *
569
+ * @returns Repository root path
570
+ * @throws GitCommandError if not in a Git repository
571
+ *
572
+ * @example
573
+ * const repoRoot = await gitModule.getRepoRoot();
574
+ * // => "/home/user/my-project"
575
+ */
576
+ getRepoRoot(): Promise<string>;
577
+ /**
578
+ * Returns the name of the current branch (HEAD)
579
+ *
580
+ * @returns Current branch name
581
+ * @throws GitCommandError if in detached HEAD state or other error
582
+ *
583
+ * @example
584
+ * const branch = await gitModule.getCurrentBranch();
585
+ * // => "main"
586
+ */
587
+ getCurrentBranch(): Promise<string>;
588
+ /**
589
+ * Get commit hash for a given reference (branch, tag, HEAD, etc.)
590
+ *
591
+ * Used by test helpers and sync operations to get commit SHAs.
592
+ * Returns the full 40-character SHA-1 hash of the commit.
593
+ *
594
+ * @param ref Git reference (default: "HEAD"). Can be:
595
+ * - "HEAD" for current commit
596
+ * - Branch name (e.g., "main", "gitgov-state")
597
+ * - Tag name (e.g., "v1.0.0")
598
+ * - Commit hash (returns the same hash)
599
+ * - Relative refs (e.g., "HEAD~1", "main^")
600
+ * @returns Commit SHA hash (full 40-character hash)
601
+ * @throws GitCommandError if ref does not exist
602
+ *
603
+ * @example
604
+ * const headHash = await git.getCommitHash("HEAD");
605
+ * // => "a1b2c3d4e5f6..."
606
+ *
607
+ * const mainHash = await git.getCommitHash("main");
608
+ * // => "f6e5d4c3b2a1..."
609
+ *
610
+ * const parentHash = await git.getCommitHash("HEAD~1");
611
+ * // => "9876543210ab..."
612
+ */
613
+ getCommitHash(ref?: string): Promise<string>;
614
+ /**
615
+ * Set a Git configuration value.
616
+ * Used for configuring repository settings like user.name, core.editor, etc.
617
+ *
618
+ * [EARS-F1, EARS-F2]
619
+ *
620
+ * @param key - Configuration key (e.g., "user.name", "core.editor")
621
+ * @param value - Configuration value
622
+ * @param scope - Configuration scope: "local" (default), "global", or "system"
623
+ * @throws GitCommandError if configuration fails
624
+ *
625
+ * @example
626
+ * ```typescript
627
+ * // Set local config (repository-specific)
628
+ * await git.setConfig('core.editor', 'vim');
629
+ *
630
+ * // Set global config (user-wide)
631
+ * await git.setConfig('user.name', 'John Doe', 'global');
632
+ *
633
+ * // Set system config (machine-wide, requires permissions)
634
+ * await git.setConfig('credential.helper', 'cache', 'system');
635
+ * ```
636
+ */
637
+ setConfig(key: string, value: string, scope?: 'local' | 'global' | 'system'): Promise<void>;
638
+ /**
639
+ * Finds the most recent common ancestor between two branches
640
+ *
641
+ * @param branchA - First branch name
642
+ * @param branchB - Second branch name
643
+ * @returns Commit hash of the merge base
644
+ * @throws BranchNotFoundError if either branch does not exist
645
+ * @throws GitCommandError if operation fails
646
+ *
647
+ * @example
648
+ * const mergeBase = await gitModule.getMergeBase("main", "feature");
649
+ * // => "a1b2c3d4e5f6..."
650
+ */
651
+ getMergeBase(branchA: string, branchB: string): Promise<string>;
652
+ /**
653
+ * Returns a list of files changed between two commits
654
+ *
655
+ * @param fromCommit - Source commit or reference
656
+ * @param toCommit - Target commit or reference
657
+ * @param pathFilter - Optional path filter (e.g., ".gitgov/")
658
+ * @returns Array of changed files with their status
659
+ * @throws GitCommandError if operation fails
660
+ *
661
+ * @example
662
+ * const changes = await gitModule.getChangedFiles("HEAD~1", "HEAD", ".gitgov/");
663
+ * // => [{ status: "M", file: ".gitgov/tasks/123.json" }]
664
+ */
665
+ getChangedFiles(fromCommit: string, toCommit: string, pathFilter: string): Promise<ChangedFile[]>;
666
+ /**
667
+ * Get list of staged files (in staging area / index)
668
+ *
669
+ * Used during conflict resolution to identify which files the user resolved and staged.
670
+ *
671
+ * @returns Array of file paths that are currently staged
672
+ * @throws GitCommandError if operation fails
673
+ *
674
+ * @example
675
+ * // After user resolves conflict and does: git add .gitgov/tasks/123.json
676
+ * const staged = await gitModule.getStagedFiles();
677
+ * // => [".gitgov/tasks/123.json"]
678
+ */
679
+ getStagedFiles(): Promise<string[]>;
680
+ /**
681
+ * Retrieves the content of a file at a specific point in history
682
+ *
683
+ * @param commitHash - Commit hash
684
+ * @param filePath - File path relative to repository root
685
+ * @returns File content as string
686
+ * @throws FileNotFoundError if file doesn't exist in that commit
687
+ * @throws GitCommandError if operation fails
688
+ *
689
+ * @example
690
+ * const content = await gitModule.getFileContent("abc123", ".gitgov/config.json");
691
+ * // => '{"version": "1.0.0"}'
692
+ */
693
+ getFileContent(commitHash: string, filePath: string): Promise<string>;
694
+ /**
695
+ * Retrieves the commit history for a branch
696
+ *
697
+ * @param branch - Branch name
698
+ * @param options - Filtering and formatting options
699
+ * @returns Array of commits ordered from newest to oldest
700
+ * @throws GitCommandError if operation fails
701
+ *
702
+ * @example
703
+ * const history = await gitModule.getCommitHistory("main", { maxCount: 10 });
704
+ * // => [{ hash: "abc123", message: "Initial commit", author: "User <email>", date: "2025-01-01T00:00:00Z" }]
705
+ */
706
+ getCommitHistory(branch: string, options?: GetCommitHistoryOptions): Promise<CommitInfo[]>;
707
+ /**
708
+ * Retrieves commit history in a specific range
709
+ *
710
+ * @param fromHash - Starting commit hash (exclusive)
711
+ * @param toHash - Ending commit hash (inclusive)
712
+ * @param options - Filtering and formatting options
713
+ * @returns Array of commits in the specified range
714
+ * @throws GitCommandError if either commit doesn't exist
715
+ *
716
+ * @example
717
+ * const commits = await gitModule.getCommitHistoryRange("abc123", "def456");
718
+ * // => [{ hash: "def456", ... }, { hash: "cba321", ... }]
719
+ */
720
+ getCommitHistoryRange(fromHash: string, toHash: string, options?: GetCommitHistoryOptions): Promise<CommitInfo[]>;
721
+ /**
722
+ * Retrieves the full commit message for a specific commit
723
+ *
724
+ * @param commitHash - Commit hash
725
+ * @returns Full commit message as string
726
+ * @throws GitCommandError if commit doesn't exist
727
+ *
728
+ * @example
729
+ * const message = await gitModule.getCommitMessage("abc123");
730
+ * // => "feat: add new feature\n\nDetailed description..."
731
+ */
732
+ getCommitMessage(commitHash: string): Promise<string>;
733
+ /**
734
+ * Checks if there are uncommitted changes in the working directory
735
+ *
736
+ * @param pathFilter - Optional path filter (e.g., ".gitgov/")
737
+ * @returns true if there are uncommitted changes, false otherwise
738
+ * @throws GitCommandError if operation fails
739
+ *
740
+ * @example
741
+ * const hasChanges = await gitModule.hasUncommittedChanges(".gitgov/");
742
+ * // => true
743
+ */
744
+ hasUncommittedChanges(pathFilter?: string): Promise<boolean>;
745
+ /**
746
+ * Checks if a rebase operation is currently in progress
747
+ *
748
+ * @returns true if rebase is in progress, false otherwise
749
+ *
750
+ * @example
751
+ * const inRebase = await gitModule.isRebaseInProgress();
752
+ * // => false
753
+ */
754
+ isRebaseInProgress(): Promise<boolean>;
755
+ /**
756
+ * Checks if a branch exists locally
757
+ *
758
+ * @param branchName - Branch name to check
759
+ * @returns true if branch exists, false otherwise
760
+ *
761
+ * @example
762
+ * const exists = await gitModule.branchExists("feature-branch");
763
+ * // => true
764
+ */
765
+ branchExists(branchName: string): Promise<boolean>;
766
+ /**
767
+ * Lists all remote branches for a given remote
768
+ *
769
+ * @param remoteName - Name of the remote (e.g., "origin")
770
+ * @returns Array of remote branch names without the remote prefix
771
+ * @throws GitCommandError if operation fails
772
+ *
773
+ * @example
774
+ * const branches = await gitModule.listRemoteBranches("origin");
775
+ * // => ["main", "develop", "gitgov-state"]
776
+ *
777
+ * @note This method only returns the branch names, not the full "origin/branch" format
778
+ */
779
+ listRemoteBranches(remoteName: string): Promise<string[]>;
780
+ /**
781
+ * Checks if a remote is configured in the git repository.
782
+ *
783
+ * @param remoteName - Name of the remote to check (e.g., "origin")
784
+ * @returns true if the remote is configured, false otherwise
785
+ *
786
+ * @example
787
+ * const hasOrigin = await gitModule.isRemoteConfigured("origin");
788
+ * // => true
789
+ */
790
+ isRemoteConfigured(remoteName: string): Promise<boolean>;
791
+ /**
792
+ * Retrieves the tracking remote for a branch
793
+ *
794
+ * @param branchName - Branch name
795
+ * @returns Remote name or null if not configured
796
+ * @throws BranchNotFoundError if branch doesn't exist
797
+ *
798
+ * @example
799
+ * const remote = await gitModule.getBranchRemote("main");
800
+ * // => "origin"
801
+ */
802
+ getBranchRemote(branchName: string): Promise<string | null>;
803
+ /**
804
+ * Retrieves the list of conflicted files during a rebase or merge
805
+ *
806
+ * @returns Array of file paths in conflict
807
+ * @throws GitCommandError if no rebase/merge in progress
808
+ *
809
+ * @example
810
+ * const conflicts = await gitModule.getConflictedFiles();
811
+ * // => [".gitgov/tasks/123.json", ".gitgov/tasks/456.json"]
812
+ */
813
+ getConflictedFiles(): Promise<string[]>;
814
+ /**
815
+ * Switches to the specified branch
816
+ *
817
+ * @param branchName - Branch name to checkout
818
+ * @throws BranchNotFoundError if branch doesn't exist
819
+ * @throws GitCommandError if operation fails
820
+ *
821
+ * @example
822
+ * await gitModule.checkoutBranch("feature-branch");
823
+ */
824
+ checkoutBranch(branchName: string): Promise<void>;
825
+ /**
826
+ * Stash uncommitted changes
827
+ *
828
+ * @param message - Optional message for the stash
829
+ * @returns Stash hash if changes were stashed, null if nothing to stash
830
+ */
831
+ stash(message?: string): Promise<string | null>;
832
+ /**
833
+ * Pop the most recent stash
834
+ *
835
+ * @returns true if stash was popped successfully, false if no stash exists
836
+ */
837
+ stashPop(): Promise<boolean>;
838
+ /**
839
+ * Drop a specific stash or the most recent one
840
+ *
841
+ * @param stashHash - Optional stash hash to drop, defaults to most recent
842
+ */
843
+ stashDrop(stashHash?: string): Promise<void>;
844
+ /**
845
+ * Creates an orphan branch (no history) and switches to it
846
+ *
847
+ * @param branchName - Orphan branch name to create
848
+ * @throws GitCommandError if branch already exists or operation fails
849
+ *
850
+ * @example
851
+ * await gitModule.checkoutOrphanBranch("gitgov-state");
852
+ */
853
+ checkoutOrphanBranch(branchName: string): Promise<void>;
854
+ /**
855
+ * Fetches the latest changes from a remote repository
856
+ *
857
+ * @param remote - Remote name (e.g., "origin")
858
+ * @throws GitCommandError if operation fails
859
+ *
860
+ * @example
861
+ * await gitModule.fetch("origin");
862
+ */
863
+ fetch(remote: string): Promise<void>;
864
+ /**
865
+ * Pulls and merges a remote branch
866
+ *
867
+ * @param remote - Remote name
868
+ * @param branchName - Branch name
869
+ * @throws MergeConflictError if merge conflicts occur
870
+ * @throws GitCommandError if operation fails
871
+ *
872
+ * @example
873
+ * await gitModule.pull("origin", "main");
874
+ */
875
+ pull(remote: string, branchName: string): Promise<void>;
876
+ /**
877
+ * Pulls and rebases a remote branch
878
+ *
879
+ * @param remote - Remote name
880
+ * @param branchName - Branch name
881
+ * @throws RebaseConflictError if rebase conflicts occur
882
+ * @throws GitCommandError if operation fails
883
+ *
884
+ * @example
885
+ * await gitModule.pullRebase("origin", "main");
886
+ */
887
+ pullRebase(remote: string, branchName: string): Promise<void>;
888
+ /**
889
+ * Resets the current branch to a specific commit, discarding all local changes
890
+ *
891
+ * @param target - Commit hash or branch name
892
+ * @throws GitCommandError if operation fails
893
+ *
894
+ * @example
895
+ * await gitModule.resetHard("HEAD~1");
896
+ */
897
+ resetHard(target: string): Promise<void>;
898
+ /**
899
+ * Checks out specific files from another branch into the current staging area
900
+ *
901
+ * @param sourceBranch - Source branch name
902
+ * @param filePaths - Array of file paths to checkout
903
+ * @throws BranchNotFoundError if source branch doesn't exist
904
+ * @throws GitCommandError if operation fails
905
+ *
906
+ * @example
907
+ * await gitModule.checkoutFilesFromBranch("main", [".gitgov/tasks/123.json"]);
908
+ */
909
+ checkoutFilesFromBranch(sourceBranch: string, filePaths: string[]): Promise<void>;
910
+ /**
911
+ * Adds files to the staging area
912
+ *
913
+ * @param filePaths - Array of file paths to add
914
+ * @param options - Optional settings (force: add ignored files)
915
+ * @throws GitCommandError if operation fails
916
+ *
917
+ * @example
918
+ * await gitModule.add([".gitgov/tasks/123.json"]);
919
+ * await gitModule.add([".gitgov"], { force: true }); // Add ignored files
920
+ */
921
+ add(filePaths: string[], options?: {
922
+ force?: boolean;
923
+ }): Promise<void>;
924
+ /**
925
+ * Removes files from both working directory and staging area
926
+ *
927
+ * @param filePaths - Array of file paths to remove
928
+ * @throws GitCommandError if operation fails
929
+ *
930
+ * @example
931
+ * await gitModule.rm([".gitgov/tasks/123.json"]);
932
+ */
933
+ rm(filePaths: string[]): Promise<void>;
934
+ /**
935
+ * Creates a new commit with staged files
936
+ *
937
+ * @param message - Commit message
938
+ * @param author - Optional commit author
939
+ * @returns Commit hash of the created commit
940
+ * @throws GitCommandError if operation fails
941
+ *
942
+ * @example
943
+ * const hash = await gitModule.commit("feat: add new task");
944
+ * // => "abc123def456..."
945
+ */
946
+ commit(message: string, author?: CommitAuthor): Promise<string>;
947
+ /**
948
+ * Creates an empty commit (no changes required)
949
+ *
950
+ * @param message - Commit message
951
+ * @param author - Optional commit author
952
+ * @returns Commit hash of the created commit
953
+ * @throws GitCommandError if operation fails
954
+ *
955
+ * @example
956
+ * const hash = await gitModule.commitAllowEmpty("chore: initialize state branch");
957
+ * // => "abc123def456..."
958
+ */
959
+ commitAllowEmpty(message: string, author?: CommitAuthor): Promise<string>;
960
+ /**
961
+ * Pushes a local branch to a remote repository
962
+ *
963
+ * @param remote - Remote name
964
+ * @param branchName - Branch name
965
+ * @throws GitCommandError if operation fails
966
+ *
967
+ * @example
968
+ * await gitModule.push("origin", "main");
969
+ */
970
+ push(remote: string, branchName: string): Promise<void>;
971
+ /**
972
+ * Pushes a local branch to a remote repository and sets up tracking
973
+ *
974
+ * @param remote - Remote name
975
+ * @param branchName - Branch name
976
+ * @throws GitCommandError if operation fails
977
+ *
978
+ * @example
979
+ * await gitModule.pushWithUpstream("origin", "feature-branch");
980
+ */
981
+ pushWithUpstream(remote: string, branchName: string): Promise<void>;
982
+ /**
983
+ * Configures tracking for a local branch with a remote branch
984
+ *
985
+ * @param branchName - Local branch name
986
+ * @param remote - Remote name
987
+ * @param remoteBranch - Remote branch name
988
+ * @throws BranchNotFoundError if local branch doesn't exist
989
+ * @throws GitCommandError if operation fails
990
+ *
991
+ * @example
992
+ * await gitModule.setUpstream("feature-branch", "origin", "feature-branch");
993
+ */
994
+ setUpstream(branchName: string, remote: string, remoteBranch: string): Promise<void>;
995
+ /**
996
+ * Continues a rebase after resolving conflicts
997
+ *
998
+ * @returns Commit hash of the rebased commit
999
+ * @throws RebaseNotInProgressError if no rebase is in progress
1000
+ * @throws GitCommandError if operation fails
1001
+ *
1002
+ * @example
1003
+ * const hash = await gitModule.rebaseContinue();
1004
+ * // => "abc123def456..."
1005
+ */
1006
+ rebaseContinue(): Promise<string>;
1007
+ /**
1008
+ * Aborts an ongoing rebase
1009
+ *
1010
+ * @throws RebaseNotInProgressError if no rebase is in progress
1011
+ * @throws GitCommandError if operation fails
1012
+ *
1013
+ * @example
1014
+ * await gitModule.rebaseAbort();
1015
+ */
1016
+ rebaseAbort(): Promise<void>;
1017
+ /**
1018
+ * Creates a new branch and switches to it (git checkout -b)
1019
+ *
1020
+ * @param branchName - Name of the branch to create
1021
+ * @param startPoint - Optional starting point (commit hash or branch name)
1022
+ * @throws GitCommandError if branch already exists or operation fails
1023
+ * @throws BranchAlreadyExistsError if the branch already exists locally
1024
+ */
1025
+ createBranch(branchName: string, startPoint?: string): Promise<void>;
1026
+ /**
1027
+ * Rebases current branch onto target branch (git rebase)
1028
+ *
1029
+ * @param targetBranch - Branch to rebase onto
1030
+ * @throws GitCommandError if rebase fails
1031
+ * @throws RebaseConflictError if conflicts are detected during rebase
1032
+ */
1033
+ rebase(targetBranch: string): Promise<void>;
1034
+ }
1035
+
1036
+ /**
1037
+ * Project Discovery Utilities
1038
+ *
1039
+ * Filesystem-based utilities for discovering GitGovernance project roots.
1040
+ * Used at CLI bootstrap to resolve projectRoot before injecting it via DI.
1041
+ *
1042
+ * NOTE: These functions should only be called at the CLI/bootstrap level.
1043
+ * Core modules receive projectRoot via constructor injection.
1044
+ */
1045
+ /**
1046
+ * Finds the project root by searching upwards for a .git directory.
1047
+ * Caches the result for subsequent calls.
1048
+ *
1049
+ * @param startPath - Starting path (default: process.cwd())
1050
+ * @returns Path to project root, or null if not found
1051
+ */
1052
+ declare function findProjectRoot(startPath?: string): string | null;
1053
+ /**
1054
+ * Finds the project root by searching upwards.
1055
+ * First looks for .gitgov (initialized project), then .git (for init).
1056
+ *
1057
+ * @param startPath - Starting path (default: process.cwd())
1058
+ * @returns Path to project root, or null if not found
1059
+ */
1060
+ declare function findGitgovRoot(startPath?: string): string | null;
1061
+ /**
1062
+ * Gets the .gitgov directory path from project root.
1063
+ *
1064
+ * @throws Error if not inside a GitGovernance project
1065
+ */
1066
+ declare function getGitgovPath(): string;
1067
+ /**
1068
+ * Checks if current directory is inside a GitGovernance project.
1069
+ */
1070
+ declare function isGitgovProject(): boolean;
1071
+ /**
1072
+ * Reset the project root cache.
1073
+ * Useful for testing when switching between project contexts.
1074
+ */
1075
+ declare function resetDiscoveryCache(): void;
1076
+
1077
+ /**
1078
+ * FsSyncStateModule - Manages state synchronization between local environment and gitgov-state branch
1079
+ *
1080
+ * Responsibilities:
1081
+ * - Create and maintain the gitgov-state branch (local and remote)
1082
+ * - Publish local changes (pushState)
1083
+ * - Pull remote changes (pullState)
1084
+ * - Resolve conflicts in a governed manner (resolveConflict)
1085
+ * - Audit state integrity (auditState)
1086
+ *
1087
+ * Philosophy:
1088
+ * - Pipeline Pattern: Sequential operations with validation at each phase
1089
+ * - Fail-Fast: Early verifications to avoid costly operations
1090
+ * - Strict Dependencies: All dependencies (git, config, identity, lint, indexer) are required for robust operations
1091
+ */
1092
+ declare class FsSyncStateModule implements ISyncStateModule {
1093
+ private git;
1094
+ private config;
1095
+ private identity;
1096
+ private lint;
1097
+ private indexer;
1098
+ /**
1099
+ * Constructor with dependency injection
1100
+ */
1101
+ constructor(dependencies: SyncStateModuleDependencies);
1102
+ /**
1103
+ * Static method to bootstrap .gitgov/ from gitgov-state branch.
1104
+ * Used when cloning a repo that has gitgov-state but .gitgov/ is not in the work branch.
1105
+ *
1106
+ * This method only requires GitModule and can be called before full SyncStateModule initialization.
1107
+ *
1108
+ * @param gitModule - GitModule instance for git operations
1109
+ * @param stateBranch - Name of the state branch (default: "gitgov-state")
1110
+ * @returns Promise<{ success: boolean; error?: string }>
1111
+ */
1112
+ static bootstrapFromStateBranch(gitModule: IGitModule, stateBranch?: string): Promise<{
1113
+ success: boolean;
1114
+ error?: string;
1115
+ }>;
1116
+ /**
1117
+ * Gets the state branch name from configuration.
1118
+ * Default: "gitgov-state"
1119
+ *
1120
+ * [EARS-A4]
1121
+ */
1122
+ getStateBranchName(): Promise<string>;
1123
+ /**
1124
+ * Ensures that the gitgov-state branch exists both locally and remotely.
1125
+ * If it doesn't exist, creates it as an orphan branch.
1126
+ *
1127
+ * Use cases (4 edge cases):
1128
+ * 1. Doesn't exist locally or remotely → Create orphan branch + initial commit + push
1129
+ * 2. Exists remotely, not locally → Fetch + create local + set tracking
1130
+ * 3. Exists locally, not remotely → Push + set tracking
1131
+ * 4. Exists both → Verify tracking
1132
+ *
1133
+ * [EARS-A1, EARS-A2, EARS-A3]
1134
+ */
1135
+ ensureStateBranch(): Promise<void>;
1136
+ /**
1137
+ * Creates the gitgov-state orphan branch with an empty initial commit.
1138
+ * Used by ensureStateBranch when the branch doesn't exist locally or remotely.
1139
+ *
1140
+ * [EARS-A1]
1141
+ */
1142
+ private createOrphanStateBranch;
1143
+ /**
1144
+ * Calculates the file delta in .gitgov/ between the current branch and gitgov-state.
1145
+ *
1146
+ * [EARS-A5]
1147
+ */
1148
+ calculateStateDelta(sourceBranch: string): Promise<StateDeltaFile[]>;
1149
+ /**
1150
+ * [EARS-B23] Detect file-level conflicts and identify remote-only changes.
1151
+ *
1152
+ * A conflict exists when:
1153
+ * 1. A file was modified by the remote during implicit pull
1154
+ * 2. AND the LOCAL USER also modified that same file (content in tempDir differs from what was in git before pull)
1155
+ *
1156
+ * This catches conflicts that git rebase can't detect because we copy files AFTER the pull.
1157
+ *
1158
+ * @param tempDir - Directory containing local .gitgov/ files (preserved before checkout)
1159
+ * @param repoRoot - Repository root path
1160
+ /**
1161
+ * Checks if a rebase is in progress.
1162
+ *
1163
+ * [EARS-D6]
1164
+ */
1165
+ isRebaseInProgress(): Promise<boolean>;
1166
+ /**
1167
+ * Checks for absence of conflict markers in specified files.
1168
+ * Returns list of files that still have markers.
1169
+ *
1170
+ * [EARS-D7]
1171
+ */
1172
+ checkConflictMarkers(filePaths: string[]): Promise<string[]>;
1173
+ /**
1174
+ * Gets the diff of conflicted files for manual analysis.
1175
+ * Useful so the actor can analyze conflicted changes before resolving.
1176
+ *
1177
+ * [EARS-E8]
1178
+ */
1179
+ getConflictDiff(filePaths?: string[]): Promise<ConflictDiff>;
1180
+ /**
1181
+ * Verifies integrity of previous resolutions in gitgov-state history.
1182
+ * Returns list of violations if any exist.
1183
+ *
1184
+ * [EARS-E1, EARS-E2, EARS-E3]
1185
+ */
1186
+ verifyResolutionIntegrity(): Promise<IntegrityViolation[]>;
1187
+ /**
1188
+ * Complete audit of gitgov-state status.
1189
+ * Verifies integrity of resolutions, signatures in Records, checksums and expected files.
1190
+ *
1191
+ * [EARS-E4, EARS-E5, EARS-E6, EARS-E7]
1192
+ */
1193
+ auditState(options?: AuditStateOptions): Promise<AuditStateReport>;
1194
+ /**
1195
+ * Publishes local state changes to gitgov-state.
1196
+ * Implements 3 phases: verification, reconciliation, publication.
1197
+ *
1198
+ * [EARS-B1 through EARS-B7]
1199
+ */
1200
+ pushState(options: SyncStatePushOptions): Promise<SyncStatePushResult>;
1201
+ /**
1202
+ * Pulls remote changes from gitgov-state to the local environment.
1203
+ * Includes automatic re-indexing if there are new changes.
1204
+ *
1205
+ * [EARS-C1 through EARS-C4]
1206
+ * [EARS-C5] Requires remote to be configured (pull without remote makes no sense)
1207
+ */
1208
+ pullState(options?: SyncStatePullOptions): Promise<SyncStatePullResult>;
1209
+ /**
1210
+ * Resolves state conflicts in a governed manner (Git-Native).
1211
+ *
1212
+ * Git-Native Flow:
1213
+ * 1. User resolves conflicts using standard Git tools (edit files, remove markers)
1214
+ * 2. User stages resolved files: git add .gitgov/
1215
+ * 3. User runs: gitgov sync resolve --reason "reason"
1216
+ *
1217
+ * This method:
1218
+ * - Verifies that a rebase is in progress
1219
+ * - Checks that no conflict markers remain in staged files
1220
+ * - Updates resolved Records with new checksums and signatures
1221
+ * - Continues the git rebase (git rebase --continue)
1222
+ * - Creates a signed resolution commit
1223
+ * - Regenerates the index
1224
+ *
1225
+ * [EARS-D1 through EARS-D7]
1226
+ */
1227
+ resolveConflict(options: SyncStateResolveOptions): Promise<SyncStateResolveResult>;
1228
+ }
1229
+
1230
+ interface WatcherStateModuleOptions {
1231
+ gitgovPath: string;
1232
+ debounceMs?: number;
1233
+ }
1234
+ interface WatcherStateModuleDependencies {
1235
+ eventBus: IEventStream;
1236
+ options: WatcherStateModuleOptions;
1237
+ }
1238
+ interface WatcherStateStatus {
1239
+ isRunning: boolean;
1240
+ watchedDirectories: string[];
1241
+ eventsEmitted: number;
1242
+ lastError: Error | undefined;
1243
+ }
1244
+
1245
+ /**
1246
+ * IWatcherStateModule - State Watcher Interface
1247
+ *
1248
+ * Defines the contract for watching .gitgov/ changes and emitting events.
1249
+ * Unidirectional: read-only observation, never writes back.
1250
+ *
1251
+ * Implementations:
1252
+ * - FsWatcherStateModule: Uses chokidar fs watcher (watcher_state/fs/)
1253
+ * - Future: CloudWatcherStateModule via realtime subscription
1254
+ *
1255
+ * @module watcher_state
1256
+ */
1257
+
1258
+ interface IWatcherStateModule {
1259
+ /** Start watching .gitgov/ directories for changes */
1260
+ start(): Promise<void>;
1261
+ /** Stop watching and release all resources */
1262
+ stop(): Promise<void>;
1263
+ /** Whether the watcher is currently active */
1264
+ isRunning(): boolean;
1265
+ /** Current status snapshot */
1266
+ getStatus(): WatcherStateStatus;
1267
+ }
1268
+
1269
+ /**
1270
+ * FsWatcherStateModule — Filesystem watcher for .gitgov/ changes
1271
+ *
1272
+ * Watches .gitgov/ subdirectories using chokidar and emits events
1273
+ * to the EventBus after debounce + checksum validation.
1274
+ */
1275
+
1276
+ declare class FsWatcherStateModule implements IWatcherStateModule {
1277
+ private eventBus;
1278
+ private gitgovPath;
1279
+ private debounceMs;
1280
+ private logger;
1281
+ private watchers;
1282
+ private watchedDirectories;
1283
+ private running;
1284
+ private debounceTimers;
1285
+ private checksums;
1286
+ private eventsEmitted;
1287
+ private lastError?;
1288
+ constructor(deps: WatcherStateModuleDependencies);
1289
+ /**
1290
+ * EARS-1: Creates watchers for existing directories in .gitgov/
1291
+ * EARS-2: Throws ProjectNotInitializedError if .gitgov/ doesn't exist
1292
+ */
1293
+ start(): Promise<void>;
1294
+ /** EARS-5: Closes watchers + cancels timers */
1295
+ stop(): Promise<void>;
1296
+ isRunning(): boolean;
1297
+ getStatus(): WatcherStateStatus;
1298
+ /**
1299
+ * EARS-3: Emits event after debounce
1300
+ * EARS-6: Debounce — N rapid changes → 1 event
1301
+ */
1302
+ private onFileChange;
1303
+ /**
1304
+ * EARS-3: Emit event to EventBus
1305
+ * EARS-4: Skip event on checksum mismatch
1306
+ * EARS-7: Handle errors gracefully
1307
+ */
1308
+ private processFileChange;
1309
+ private emitEvent;
1310
+ private extractRecordType;
1311
+ private extractRecordId;
1312
+ }
1313
+
1314
+ /**
1315
+ * Filesystem-based Agent Runner - Executes agents based on their engine.type.
1316
+ *
1317
+ * Responsibilities:
1318
+ * - Load AgentRecords from .gitgov/agents/
1319
+ * - Execute via appropriate backend (local, api, mcp, custom)
1320
+ * - Capture responses and write ExecutionRecords
1321
+ * - Emit events via EventBus
1322
+ */
1323
+ declare class FsAgentRunner implements IAgentRunner {
1324
+ private gitgovPath;
1325
+ private projectRoot;
1326
+ private identityAdapter;
1327
+ private executionAdapter;
1328
+ private eventBus;
1329
+ /** Protocol handlers for CustomBackend */
1330
+ readonly protocolHandlers: ProtocolHandlerRegistry | undefined;
1331
+ private runtimeHandlers;
1332
+ private localBackend;
1333
+ private apiBackend;
1334
+ private mcpBackend;
1335
+ private customBackend;
1336
+ constructor(deps: AgentRunnerDependencies);
1337
+ /**
1338
+ * Executes an agent once and returns the response.
1339
+ * TaskRecord must exist before calling this method.
1340
+ */
1341
+ runOnce(opts: RunOptions): Promise<AgentResponse>;
1342
+ /**
1343
+ * [EARS-A1, A2] Loads AgentRecord from .gitgov/agents/agent-{id}.json
1344
+ */
1345
+ private loadAgent;
1346
+ /**
1347
+ * [EARS-I4] Emits event via EventBus if available.
1348
+ * Works silently without EventBus.
1349
+ */
1350
+ private emitEvent;
1351
+ }
1352
+
1353
+ /**
1354
+ * Filesystem AgentRunner implementation
1355
+ *
1356
+ * This module provides the filesystem-based implementation of IAgentRunner:
1357
+ * - FsAgentRunner: Loads AgentRecords from .gitgov/agents/
1358
+ * - createAgentRunner(): Factory function for DI
1359
+ *
1360
+ * Note: LocalBackend is re-exported from backends/ for convenience.
1361
+ * Use @gitgov/core for direct backend imports.
1362
+ */
1363
+
1364
+ /**
1365
+ * Factory function to create a filesystem-based AgentRunner.
1366
+ */
1367
+ declare function createAgentRunner(deps: AgentRunnerDependencies): IAgentRunner;
1368
+
1369
+ export { DEFAULT_ID_ENCODER, type FileSystem, FsAgentRunner, AgentRunnerDependencies as FsAgentRunnerDependencies, FsConfigStore, type FsFixOptions, FsLintModule, type FsLintModuleDependencies, type FsLintOptions, FsProjectInitializer, FsRecordStore, FsSessionStore, FsSyncStateModule, FsWatcherStateModule, LocalGitModule as GitModule, GitModuleDependencies, type IFsLintModule, IGitModule, LocalGitModule, createAgentRunner, createConfigManager, createSessionManager, findGitgovRoot, findProjectRoot, getGitgovPath, isGitgovProject, resetDiscoveryCache };