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