@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.
- package/README.md +151 -270
- package/dist/src/agent_runner-ByOUWOt6.d.ts +2580 -0
- package/dist/src/fs.d.ts +1369 -0
- package/dist/src/fs.js +8483 -0
- package/dist/src/fs.js.map +1 -0
- package/dist/src/index--ahcnsG3.d.ts +798 -0
- package/dist/src/index.d.ts +1706 -5213
- package/dist/src/index.js +4779 -8956
- package/dist/src/index.js.map +1 -1
- package/dist/src/memory.d.ts +262 -0
- package/dist/src/memory.js +790 -0
- package/dist/src/memory.js.map +1 -0
- package/dist/src/memory_file_lister-BkQ_C3ZU.d.ts +221 -0
- package/package.json +19 -8
- package/prompts/gitgov_agent_prompt.md +0 -480
|
@@ -0,0 +1,798 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RecordStore<T> - Generic interface for record persistence
|
|
3
|
+
*
|
|
4
|
+
* Abstracts CRUD operations without assuming storage backend.
|
|
5
|
+
* Each implementation decides how to persist (fs, memory, db, remote).
|
|
6
|
+
*/
|
|
7
|
+
interface RecordStore<T> {
|
|
8
|
+
/**
|
|
9
|
+
* Gets a record by ID
|
|
10
|
+
* @returns The record or null if it doesn't exist
|
|
11
|
+
*/
|
|
12
|
+
get(id: string): Promise<T | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Persists a record
|
|
15
|
+
* @param id - Unique identifier
|
|
16
|
+
* @param value - The record to persist
|
|
17
|
+
*/
|
|
18
|
+
put(id: string, value: T): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Deletes a record
|
|
21
|
+
* @param id - Identifier of the record to delete
|
|
22
|
+
*/
|
|
23
|
+
delete(id: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Lists all record IDs
|
|
26
|
+
* @returns Array of IDs
|
|
27
|
+
*/
|
|
28
|
+
list(): Promise<string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Checks if a record exists
|
|
31
|
+
* @param id - Identifier to check
|
|
32
|
+
*/
|
|
33
|
+
exists(id: string): Promise<boolean>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ConfigManager Types
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* GitGovernance Configuration
|
|
41
|
+
* Based on config_file.md blueprint
|
|
42
|
+
*/
|
|
43
|
+
type GitGovConfig = {
|
|
44
|
+
protocolVersion: string;
|
|
45
|
+
projectId: string;
|
|
46
|
+
projectName: string;
|
|
47
|
+
rootCycle: string;
|
|
48
|
+
state?: {
|
|
49
|
+
branch?: string;
|
|
50
|
+
sync?: {
|
|
51
|
+
strategy?: "manual" | "immediate" | "batched";
|
|
52
|
+
maxRetries?: number;
|
|
53
|
+
pushIntervalSeconds?: number;
|
|
54
|
+
batchIntervalSeconds?: number;
|
|
55
|
+
};
|
|
56
|
+
defaults?: {
|
|
57
|
+
pullScheduler?: {
|
|
58
|
+
defaultIntervalSeconds?: number;
|
|
59
|
+
defaultEnabled?: boolean;
|
|
60
|
+
defaultContinueOnNetworkError?: boolean;
|
|
61
|
+
defaultStopOnConflict?: boolean;
|
|
62
|
+
};
|
|
63
|
+
fileWatcher?: {
|
|
64
|
+
defaultDebounceMs?: number;
|
|
65
|
+
defaultIgnoredPatterns?: string[];
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
audit?: {
|
|
69
|
+
lastFullAuditCommit?: string;
|
|
70
|
+
lastFullAuditTimestamp?: string;
|
|
71
|
+
lastFullAuditFindingsCount?: number;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Audit state stored in config.json for incremental mode
|
|
77
|
+
*/
|
|
78
|
+
type AuditState = {
|
|
79
|
+
lastFullAuditCommit: string | null;
|
|
80
|
+
lastFullAuditTimestamp: string | null;
|
|
81
|
+
lastFullAuditFindingsCount: number | null;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Sync configuration from config.json
|
|
85
|
+
*/
|
|
86
|
+
type SyncConfig = {
|
|
87
|
+
strategy: "manual" | "immediate" | "batched";
|
|
88
|
+
maxRetries: number;
|
|
89
|
+
pushIntervalSeconds: number;
|
|
90
|
+
batchIntervalSeconds: number;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Sync defaults from config.json
|
|
94
|
+
*/
|
|
95
|
+
type SyncDefaults = {
|
|
96
|
+
pullScheduler: {
|
|
97
|
+
defaultIntervalSeconds: number;
|
|
98
|
+
defaultEnabled: boolean;
|
|
99
|
+
defaultContinueOnNetworkError: boolean;
|
|
100
|
+
defaultStopOnConflict: boolean;
|
|
101
|
+
};
|
|
102
|
+
fileWatcher: {
|
|
103
|
+
defaultDebounceMs: number;
|
|
104
|
+
defaultIgnoredPatterns: string[];
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Audit state update payload
|
|
109
|
+
*/
|
|
110
|
+
type AuditStateUpdate = {
|
|
111
|
+
lastFullAuditCommit: string;
|
|
112
|
+
lastFullAuditTimestamp: string;
|
|
113
|
+
lastFullAuditFindingsCount: number;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* IConfigManager interface
|
|
117
|
+
*
|
|
118
|
+
* Provides typed access to GitGovernance project configuration.
|
|
119
|
+
* Configuration is versioned in Git and shared between collaborators.
|
|
120
|
+
*/
|
|
121
|
+
interface IConfigManager {
|
|
122
|
+
/**
|
|
123
|
+
* Load GitGovernance configuration
|
|
124
|
+
*/
|
|
125
|
+
loadConfig(): Promise<GitGovConfig | null>;
|
|
126
|
+
/**
|
|
127
|
+
* Get root cycle from configuration
|
|
128
|
+
*/
|
|
129
|
+
getRootCycle(): Promise<string | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Get project information from configuration
|
|
132
|
+
*/
|
|
133
|
+
getProjectInfo(): Promise<{
|
|
134
|
+
id: string;
|
|
135
|
+
name: string;
|
|
136
|
+
} | null>;
|
|
137
|
+
/**
|
|
138
|
+
* Get sync configuration from config.json
|
|
139
|
+
* Returns sync strategy and related settings with defaults
|
|
140
|
+
*/
|
|
141
|
+
getSyncConfig(): Promise<SyncConfig | null>;
|
|
142
|
+
/**
|
|
143
|
+
* Get sync defaults from config.json
|
|
144
|
+
* Returns recommended defaults for pullScheduler and fileWatcher
|
|
145
|
+
*/
|
|
146
|
+
getSyncDefaults(): Promise<SyncDefaults>;
|
|
147
|
+
/**
|
|
148
|
+
* Get audit state from config.json
|
|
149
|
+
* Returns last full audit commit and timestamp for incremental mode
|
|
150
|
+
*/
|
|
151
|
+
getAuditState(): Promise<AuditState>;
|
|
152
|
+
/**
|
|
153
|
+
* Update audit state in config.json after a full audit
|
|
154
|
+
* This is used to enable incremental audits
|
|
155
|
+
*/
|
|
156
|
+
updateAuditState(auditState: AuditStateUpdate): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* Get state branch name from configuration
|
|
159
|
+
*/
|
|
160
|
+
getStateBranch(): Promise<string>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* SessionManager Types
|
|
165
|
+
*/
|
|
166
|
+
/**
|
|
167
|
+
* Sync status for an actor's synchronization state.
|
|
168
|
+
*/
|
|
169
|
+
type SyncStatus = {
|
|
170
|
+
lastSyncPush?: string;
|
|
171
|
+
lastSyncPull?: string;
|
|
172
|
+
status?: 'synced' | 'pending' | 'pulling' | 'pushing' | 'conflict';
|
|
173
|
+
lastError?: string;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* State for a specific actor on this machine.
|
|
177
|
+
*/
|
|
178
|
+
type ActorState = {
|
|
179
|
+
activeTaskId?: string | undefined;
|
|
180
|
+
activeCycleId?: string | undefined;
|
|
181
|
+
lastSync?: string;
|
|
182
|
+
syncStatus?: SyncStatus;
|
|
183
|
+
[key: string]: unknown;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* GitGovernance Session State
|
|
187
|
+
* Based on session_state.md blueprint
|
|
188
|
+
*/
|
|
189
|
+
type GitGovSession = {
|
|
190
|
+
cloud?: {
|
|
191
|
+
sessionToken?: string;
|
|
192
|
+
};
|
|
193
|
+
lastSession?: {
|
|
194
|
+
actorId: string;
|
|
195
|
+
timestamp: string;
|
|
196
|
+
};
|
|
197
|
+
actorState?: Record<string, ActorState>;
|
|
198
|
+
syncPreferences?: {
|
|
199
|
+
pullScheduler?: {
|
|
200
|
+
enabled?: boolean;
|
|
201
|
+
pullIntervalSeconds?: number;
|
|
202
|
+
continueOnNetworkError?: boolean;
|
|
203
|
+
stopOnConflict?: boolean;
|
|
204
|
+
};
|
|
205
|
+
fileWatcher?: {
|
|
206
|
+
enabled?: boolean;
|
|
207
|
+
debounceMs?: number;
|
|
208
|
+
ignoredPatterns?: string[];
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Sync preferences update payload
|
|
214
|
+
*/
|
|
215
|
+
type SyncPreferencesUpdate = {
|
|
216
|
+
pullScheduler?: Partial<{
|
|
217
|
+
enabled: boolean;
|
|
218
|
+
pullIntervalSeconds: number;
|
|
219
|
+
continueOnNetworkError: boolean;
|
|
220
|
+
stopOnConflict: boolean;
|
|
221
|
+
}>;
|
|
222
|
+
fileWatcher?: Partial<{
|
|
223
|
+
enabled: boolean;
|
|
224
|
+
debounceMs: number;
|
|
225
|
+
ignoredPatterns: string[];
|
|
226
|
+
}>;
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* ISessionManager interface
|
|
230
|
+
*
|
|
231
|
+
* Provides typed access to GitGovernance session state.
|
|
232
|
+
* Session state is ephemeral, machine-local, and NOT versioned in Git.
|
|
233
|
+
*/
|
|
234
|
+
interface ISessionManager {
|
|
235
|
+
/**
|
|
236
|
+
* Load GitGovernance session state
|
|
237
|
+
* [EARS-B9] Auto-detects actor from .key files if no session or no actorId exists
|
|
238
|
+
*/
|
|
239
|
+
loadSession(): Promise<GitGovSession | null>;
|
|
240
|
+
/**
|
|
241
|
+
* [EARS-B9] Detect actor from .key files in .gitgov/actors/
|
|
242
|
+
*/
|
|
243
|
+
detectActorFromKeyFiles(): Promise<string | null>;
|
|
244
|
+
/**
|
|
245
|
+
* Get actor state for a specific actor
|
|
246
|
+
*/
|
|
247
|
+
getActorState(actorId: string): Promise<ActorState | null>;
|
|
248
|
+
/**
|
|
249
|
+
* Update actor state for a specific actor
|
|
250
|
+
*/
|
|
251
|
+
updateActorState(actorId: string, state: Partial<ActorState>): Promise<void>;
|
|
252
|
+
/**
|
|
253
|
+
* Get cloud session token
|
|
254
|
+
*/
|
|
255
|
+
getCloudSessionToken(): Promise<string | null>;
|
|
256
|
+
/**
|
|
257
|
+
* Get sync preferences from session
|
|
258
|
+
*/
|
|
259
|
+
getSyncPreferences(): Promise<GitGovSession['syncPreferences'] | null>;
|
|
260
|
+
/**
|
|
261
|
+
* Update sync preferences in .session.json
|
|
262
|
+
* These are local machine preferences that override project defaults
|
|
263
|
+
*/
|
|
264
|
+
updateSyncPreferences(preferences: SyncPreferencesUpdate): Promise<void>;
|
|
265
|
+
/**
|
|
266
|
+
* Get last session info (last human who interacted)
|
|
267
|
+
*/
|
|
268
|
+
getLastSession(): Promise<{
|
|
269
|
+
actorId: string;
|
|
270
|
+
timestamp: string;
|
|
271
|
+
} | null>;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* SessionStore - Session persistence abstraction
|
|
276
|
+
*
|
|
277
|
+
* Interface for storing and retrieving local session state (.session.json).
|
|
278
|
+
* Session state is ephemeral, machine-local, and NOT versioned in Git.
|
|
279
|
+
*
|
|
280
|
+
* Implementations:
|
|
281
|
+
* - FsSessionStore: Filesystem-based (production)
|
|
282
|
+
* - MemorySessionStore: In-memory (tests, serverless)
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Interface for session state persistence.
|
|
287
|
+
*
|
|
288
|
+
* Session state includes:
|
|
289
|
+
* - Actor state (activeTaskId, activeCycleId, syncStatus)
|
|
290
|
+
* - Sync preferences (pullScheduler, fileWatcher settings)
|
|
291
|
+
* - Cloud session tokens
|
|
292
|
+
* - Last session information
|
|
293
|
+
*
|
|
294
|
+
* Unlike ConfigStore, SessionStore handles ephemeral, machine-local state
|
|
295
|
+
* that is NOT shared between collaborators.
|
|
296
|
+
*/
|
|
297
|
+
interface SessionStore {
|
|
298
|
+
/**
|
|
299
|
+
* Load session state from storage.
|
|
300
|
+
*
|
|
301
|
+
* @returns GitGovSession object or null if not found
|
|
302
|
+
*/
|
|
303
|
+
loadSession(): Promise<GitGovSession | null>;
|
|
304
|
+
/**
|
|
305
|
+
* Save session state to storage.
|
|
306
|
+
*
|
|
307
|
+
* @param session - The session state to persist
|
|
308
|
+
*/
|
|
309
|
+
saveSession(session: GitGovSession): Promise<void>;
|
|
310
|
+
/**
|
|
311
|
+
* Detect actor from private key files.
|
|
312
|
+
*
|
|
313
|
+
* Optional method for implementations that support actor auto-detection
|
|
314
|
+
* from .key files in the actors directory.
|
|
315
|
+
*
|
|
316
|
+
* @returns Actor ID (e.g., "human:camilo-v2") or null if not detectable
|
|
317
|
+
*/
|
|
318
|
+
detectActorFromKeyFiles?(): Promise<string | null>;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* ConfigStore Interface
|
|
323
|
+
*
|
|
324
|
+
* Abstraction for config.json persistence.
|
|
325
|
+
* Enables backend-agnostic access to GitGovernance project configuration
|
|
326
|
+
* (filesystem, memory for tests, or future cloud backends).
|
|
327
|
+
*
|
|
328
|
+
* NOTE: Session state (.session.json) is handled by SessionStore, not ConfigStore.
|
|
329
|
+
* This separation allows different backends for config (immutable, versioned)
|
|
330
|
+
* vs session (ephemeral, local).
|
|
331
|
+
*/
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Interface for project configuration persistence.
|
|
335
|
+
*
|
|
336
|
+
* ConfigStore manages the project config.json file which is:
|
|
337
|
+
* - Versioned in Git (shared between collaborators)
|
|
338
|
+
* - Contains project-level settings (protocolVersion, projectId, rootCycle, etc.)
|
|
339
|
+
* - Rarely changes after initial setup
|
|
340
|
+
*
|
|
341
|
+
* Implementations:
|
|
342
|
+
* - FsConfigStore: Filesystem-based (.gitgov/config.json)
|
|
343
|
+
* - MemoryConfigStore: In-memory for tests
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```typescript
|
|
347
|
+
* // Production with filesystem
|
|
348
|
+
* const store = new FsConfigStore('/path/to/project');
|
|
349
|
+
* const config = await store.loadConfig();
|
|
350
|
+
*
|
|
351
|
+
* // Tests with memory
|
|
352
|
+
* const store = new MemoryConfigStore();
|
|
353
|
+
* store.setConfig({ protocolVersion: '1.0', ... });
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
interface ConfigStore {
|
|
357
|
+
/**
|
|
358
|
+
* Load project configuration from config.json
|
|
359
|
+
*
|
|
360
|
+
* @returns GitGovConfig or null if not found/invalid
|
|
361
|
+
*/
|
|
362
|
+
loadConfig(): Promise<GitGovConfig | null>;
|
|
363
|
+
/**
|
|
364
|
+
* Save project configuration to config.json
|
|
365
|
+
*
|
|
366
|
+
* @param config - Configuration to persist
|
|
367
|
+
*/
|
|
368
|
+
saveConfig(config: GitGovConfig): Promise<void>;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* KeyProvider Interface
|
|
373
|
+
*
|
|
374
|
+
* Abstracts private key storage for Actor signing operations.
|
|
375
|
+
* Enables different backends: filesystem (development), environment variables (serverless),
|
|
376
|
+
* or cloud KMS (enterprise).
|
|
377
|
+
*
|
|
378
|
+
* @module key_provider
|
|
379
|
+
*/
|
|
380
|
+
/**
|
|
381
|
+
* Error codes for KeyProvider operations.
|
|
382
|
+
*/
|
|
383
|
+
type KeyProviderErrorCode = 'KEY_NOT_FOUND' | 'KEY_READ_ERROR' | 'KEY_WRITE_ERROR' | 'KEY_DELETE_ERROR' | 'INVALID_KEY_FORMAT' | 'INVALID_ACTOR_ID';
|
|
384
|
+
/**
|
|
385
|
+
* Error thrown when key operations fail.
|
|
386
|
+
*/
|
|
387
|
+
declare class KeyProviderError extends Error {
|
|
388
|
+
readonly code: KeyProviderErrorCode;
|
|
389
|
+
readonly actorId?: string | undefined;
|
|
390
|
+
constructor(message: string, code: KeyProviderErrorCode, actorId?: string | undefined);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Interface for managing private key storage.
|
|
394
|
+
* Implementations handle the actual persistence mechanism.
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```typescript
|
|
398
|
+
* // Filesystem backend (development)
|
|
399
|
+
* const provider = new FsKeyProvider({ actorsDir: '.gitgov/actors' });
|
|
400
|
+
*
|
|
401
|
+
* // Environment backend (serverless)
|
|
402
|
+
* const provider = new EnvKeyProvider({ prefix: 'GITGOV_KEY_' });
|
|
403
|
+
*
|
|
404
|
+
* // Usage
|
|
405
|
+
* const privateKey = await provider.getPrivateKey('actor:human:alice');
|
|
406
|
+
* if (privateKey) {
|
|
407
|
+
* const signature = signPayload(payload, privateKey, actorId, role);
|
|
408
|
+
* }
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
interface KeyProvider {
|
|
412
|
+
/**
|
|
413
|
+
* Retrieves the private key for an actor.
|
|
414
|
+
* @param actorId - The actor's ID (e.g., 'actor:human:alice')
|
|
415
|
+
* @returns The base64-encoded private key, or null if not found
|
|
416
|
+
*/
|
|
417
|
+
getPrivateKey(actorId: string): Promise<string | null>;
|
|
418
|
+
/**
|
|
419
|
+
* Stores a private key for an actor.
|
|
420
|
+
* @param actorId - The actor's ID
|
|
421
|
+
* @param privateKey - The base64-encoded private key
|
|
422
|
+
* @throws KeyProviderError if write fails
|
|
423
|
+
*/
|
|
424
|
+
setPrivateKey(actorId: string, privateKey: string): Promise<void>;
|
|
425
|
+
/**
|
|
426
|
+
* Checks if a private key exists for an actor.
|
|
427
|
+
* @param actorId - The actor's ID
|
|
428
|
+
* @returns true if key exists, false otherwise
|
|
429
|
+
*/
|
|
430
|
+
hasPrivateKey(actorId: string): Promise<boolean>;
|
|
431
|
+
/**
|
|
432
|
+
* Deletes the private key for an actor.
|
|
433
|
+
* @param actorId - The actor's ID
|
|
434
|
+
* @returns true if key was deleted, false if it didn't exist
|
|
435
|
+
*/
|
|
436
|
+
deletePrivateKey(actorId: string): Promise<boolean>;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Options for file listing.
|
|
441
|
+
*/
|
|
442
|
+
type FileListOptions = {
|
|
443
|
+
/** Glob patterns to ignore (e.g., ['node_modules/**']) */
|
|
444
|
+
ignore?: string[];
|
|
445
|
+
/** Only return files (not directories). Default: true */
|
|
446
|
+
onlyFiles?: boolean;
|
|
447
|
+
/** Return absolute paths instead of relative. Default: false */
|
|
448
|
+
absolute?: boolean;
|
|
449
|
+
/** Maximum depth to traverse. Default: unlimited */
|
|
450
|
+
maxDepth?: number;
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* File statistics returned by stat().
|
|
454
|
+
*/
|
|
455
|
+
type FileStats = {
|
|
456
|
+
/** File size in bytes */
|
|
457
|
+
size: number;
|
|
458
|
+
/** Last modification time as timestamp (ms since epoch) */
|
|
459
|
+
mtime: number;
|
|
460
|
+
/** Whether it's a file (not directory) */
|
|
461
|
+
isFile: boolean;
|
|
462
|
+
};
|
|
463
|
+
/**
|
|
464
|
+
* Options for FsFileLister.
|
|
465
|
+
*/
|
|
466
|
+
type FsFileListerOptions = {
|
|
467
|
+
/** Base directory for all operations */
|
|
468
|
+
cwd: string;
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Options for MemoryFileLister.
|
|
472
|
+
*/
|
|
473
|
+
type MemoryFileListerOptions = {
|
|
474
|
+
/** Map of filePath -> content */
|
|
475
|
+
files?: Map<string, string> | Record<string, string>;
|
|
476
|
+
/** Map of filePath -> stats (optional, generated if not provided) */
|
|
477
|
+
stats?: Map<string, FileStats>;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* FileLister Interface
|
|
482
|
+
*
|
|
483
|
+
* Abstracts file listing and reading operations for serverless compatibility.
|
|
484
|
+
* Enables modules like ScopeSelector and IndexerAdapter to work without
|
|
485
|
+
* direct filesystem dependencies.
|
|
486
|
+
*
|
|
487
|
+
* @module file_lister
|
|
488
|
+
*/
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Interface for listing and reading files.
|
|
492
|
+
* Abstracts filesystem operations for serverless compatibility.
|
|
493
|
+
*
|
|
494
|
+
* @example
|
|
495
|
+
* ```typescript
|
|
496
|
+
* // Filesystem backend (development/CLI)
|
|
497
|
+
* import { FsFileLister } from '@gitgov/core/fs';
|
|
498
|
+
* const lister = new FsFileLister({ cwd: '/path/to/project' });
|
|
499
|
+
*
|
|
500
|
+
* // Memory backend (testing)
|
|
501
|
+
* import { MemoryFileLister } from '@gitgov/core/memory';
|
|
502
|
+
* const lister = new MemoryFileLister({ files: { 'src/index.ts': 'code...' } });
|
|
503
|
+
*
|
|
504
|
+
* // Usage
|
|
505
|
+
* const files = await lister.list(['**\/*.ts']);
|
|
506
|
+
* const content = await lister.read('src/index.ts');
|
|
507
|
+
* ```
|
|
508
|
+
*/
|
|
509
|
+
interface FileLister {
|
|
510
|
+
/**
|
|
511
|
+
* [EARS-FL01] Lists files matching glob patterns.
|
|
512
|
+
* @param patterns - Glob patterns to match (e.g., ['**\/*.ts', 'src/**'])
|
|
513
|
+
* @param options - Optional configuration for listing
|
|
514
|
+
* @returns Array of file paths relative to cwd
|
|
515
|
+
*/
|
|
516
|
+
list(patterns: string[], options?: FileListOptions): Promise<string[]>;
|
|
517
|
+
/**
|
|
518
|
+
* [EARS-FL02] Checks if a file exists.
|
|
519
|
+
* @param filePath - Path relative to cwd
|
|
520
|
+
* @returns true if file exists, false otherwise
|
|
521
|
+
*/
|
|
522
|
+
exists(filePath: string): Promise<boolean>;
|
|
523
|
+
/**
|
|
524
|
+
* [EARS-FL03] Reads file content as string.
|
|
525
|
+
* @param filePath - Path relative to cwd
|
|
526
|
+
* @returns File content as UTF-8 string
|
|
527
|
+
* @throws FileListerError if file doesn't exist or can't be read
|
|
528
|
+
*/
|
|
529
|
+
read(filePath: string): Promise<string>;
|
|
530
|
+
/**
|
|
531
|
+
* [EARS-FL04] Gets file statistics.
|
|
532
|
+
* @param filePath - Path relative to cwd
|
|
533
|
+
* @returns File stats (size, mtime)
|
|
534
|
+
* @throws FileListerError if file doesn't exist
|
|
535
|
+
*/
|
|
536
|
+
stat(filePath: string): Promise<FileStats>;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Type Definitions for GitModule
|
|
541
|
+
*
|
|
542
|
+
* These types define the contracts for Git operations,
|
|
543
|
+
* dependencies, and data structures used throughout the module.
|
|
544
|
+
*/
|
|
545
|
+
/**
|
|
546
|
+
* Options for executing shell commands
|
|
547
|
+
*/
|
|
548
|
+
type ExecOptions = {
|
|
549
|
+
/** Working directory for the command */
|
|
550
|
+
cwd?: string;
|
|
551
|
+
/** Additional environment variables */
|
|
552
|
+
env?: Record<string, string>;
|
|
553
|
+
/** Timeout in milliseconds */
|
|
554
|
+
timeout?: number;
|
|
555
|
+
};
|
|
556
|
+
/**
|
|
557
|
+
* Result of executing a shell command
|
|
558
|
+
*/
|
|
559
|
+
type ExecResult = {
|
|
560
|
+
/** Exit code (0 = success) */
|
|
561
|
+
exitCode: number;
|
|
562
|
+
/** Standard output */
|
|
563
|
+
stdout: string;
|
|
564
|
+
/** Standard error output */
|
|
565
|
+
stderr: string;
|
|
566
|
+
};
|
|
567
|
+
/**
|
|
568
|
+
* Dependencies required by LocalGitModule
|
|
569
|
+
*
|
|
570
|
+
* This module uses dependency injection to allow testing with mocks
|
|
571
|
+
* and support different execution environments.
|
|
572
|
+
*/
|
|
573
|
+
type GitModuleDependencies = {
|
|
574
|
+
/** Path to the Git repository root (optional, auto-detected if not provided) */
|
|
575
|
+
repoRoot?: string;
|
|
576
|
+
/** Function to execute shell commands (required) */
|
|
577
|
+
execCommand: (command: string, args: string[], options?: ExecOptions) => Promise<ExecResult>;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Options for retrieving commit history
|
|
581
|
+
*/
|
|
582
|
+
type GetCommitHistoryOptions = {
|
|
583
|
+
/** Maximum number of commits to return */
|
|
584
|
+
maxCount?: number;
|
|
585
|
+
/** Path filter (e.g., ".gitgov/") */
|
|
586
|
+
pathFilter?: string;
|
|
587
|
+
/** Output format (default: "json") */
|
|
588
|
+
format?: 'json' | 'text';
|
|
589
|
+
};
|
|
590
|
+
/**
|
|
591
|
+
* Information about a commit in the history
|
|
592
|
+
*/
|
|
593
|
+
type CommitInfo = {
|
|
594
|
+
/** Commit hash */
|
|
595
|
+
hash: string;
|
|
596
|
+
/** Commit message */
|
|
597
|
+
message: string;
|
|
598
|
+
/** Commit author (name <email>) */
|
|
599
|
+
author: string;
|
|
600
|
+
/** Commit date (ISO 8601) */
|
|
601
|
+
date: string;
|
|
602
|
+
/** List of modified files (optional) */
|
|
603
|
+
files?: string[];
|
|
604
|
+
};
|
|
605
|
+
/**
|
|
606
|
+
* Information about a changed file
|
|
607
|
+
*/
|
|
608
|
+
type ChangedFile = {
|
|
609
|
+
/** Change status: A (Added), M (Modified), D (Deleted) */
|
|
610
|
+
status: 'A' | 'M' | 'D';
|
|
611
|
+
/** File path relative to repository root */
|
|
612
|
+
file: string;
|
|
613
|
+
};
|
|
614
|
+
/**
|
|
615
|
+
* Author information for commits
|
|
616
|
+
*/
|
|
617
|
+
type CommitAuthor = {
|
|
618
|
+
/** Author name */
|
|
619
|
+
name: string;
|
|
620
|
+
/** Author email */
|
|
621
|
+
email: string;
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Custom Error Classes for GitModule
|
|
626
|
+
*
|
|
627
|
+
* These errors provide typed exceptions for better error handling
|
|
628
|
+
* and diagnostics in the Git module operations.
|
|
629
|
+
*/
|
|
630
|
+
/**
|
|
631
|
+
* Base error class for all Git-related errors
|
|
632
|
+
*/
|
|
633
|
+
declare class GitError extends Error {
|
|
634
|
+
constructor(message: string);
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Error thrown when a Git command fails
|
|
638
|
+
*/
|
|
639
|
+
declare class GitCommandError extends GitError {
|
|
640
|
+
readonly stderr: string;
|
|
641
|
+
readonly stdout?: string | undefined;
|
|
642
|
+
readonly command?: string | undefined;
|
|
643
|
+
constructor(message: string, stderr?: string, command?: string | undefined, stdout?: string);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Error thrown when a branch does not exist
|
|
647
|
+
*/
|
|
648
|
+
declare class BranchNotFoundError extends GitError {
|
|
649
|
+
readonly branchName: string;
|
|
650
|
+
constructor(branchName: string);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Error thrown when a file does not exist in a commit
|
|
654
|
+
*/
|
|
655
|
+
declare class FileNotFoundError extends GitError {
|
|
656
|
+
readonly filePath: string;
|
|
657
|
+
readonly commitHash: string;
|
|
658
|
+
constructor(filePath: string, commitHash: string);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Error thrown when a merge conflict occurs
|
|
662
|
+
*/
|
|
663
|
+
declare class MergeConflictError extends GitError {
|
|
664
|
+
readonly conflictedFiles: string[];
|
|
665
|
+
constructor(conflictedFiles: string[]);
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Error thrown when a rebase conflict occurs
|
|
669
|
+
*/
|
|
670
|
+
declare class RebaseConflictError extends GitError {
|
|
671
|
+
readonly conflictedFiles: string[];
|
|
672
|
+
constructor(conflictedFiles: string[]);
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Error thrown when trying to continue/abort a rebase that is not in progress
|
|
676
|
+
*/
|
|
677
|
+
declare class RebaseNotInProgressError extends GitError {
|
|
678
|
+
constructor();
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Error thrown when trying to create a branch that already exists
|
|
682
|
+
*/
|
|
683
|
+
declare class BranchAlreadyExistsError extends GitError {
|
|
684
|
+
readonly branchName: string;
|
|
685
|
+
constructor(branchName: string);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* GitModule - Low-level Git Operations
|
|
690
|
+
*
|
|
691
|
+
* This module provides backend-agnostic access to Git operations.
|
|
692
|
+
*
|
|
693
|
+
* IMPORTANT: This module only exports the interface and types.
|
|
694
|
+
* For implementations, use:
|
|
695
|
+
* - @gitgov/core/fs for LocalGitModule (CLI-based)
|
|
696
|
+
* - @gitgov/core/memory for MemoryGitModule (testing)
|
|
697
|
+
*
|
|
698
|
+
* @example
|
|
699
|
+
* ```typescript
|
|
700
|
+
* // Import interface and types
|
|
701
|
+
* import type { IGitModule } from '@gitgov/core';
|
|
702
|
+
*
|
|
703
|
+
* // Import CLI implementation from fs entry point
|
|
704
|
+
* import { LocalGitModule } from '@gitgov/core/fs';
|
|
705
|
+
*
|
|
706
|
+
* // Import memory implementation from memory entry point
|
|
707
|
+
* import { MemoryGitModule } from '@gitgov/core/memory';
|
|
708
|
+
* ```
|
|
709
|
+
*
|
|
710
|
+
* @module git
|
|
711
|
+
*/
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* IGitModule - Interface for Git operations
|
|
715
|
+
*
|
|
716
|
+
* Implementations:
|
|
717
|
+
* - LocalGitModule: Uses execCommand to run git CLI (production)
|
|
718
|
+
* - MemoryGitModule: In-memory mock for unit tests
|
|
719
|
+
* - Future: GitHubGitModule for SaaS API-based operations
|
|
720
|
+
*
|
|
721
|
+
* All methods are async to support both local CLI execution
|
|
722
|
+
* and future API-based implementations (GitHub REST/GraphQL).
|
|
723
|
+
*/
|
|
724
|
+
interface IGitModule {
|
|
725
|
+
exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
726
|
+
init(): Promise<void>;
|
|
727
|
+
getRepoRoot(): Promise<string>;
|
|
728
|
+
getCurrentBranch(): Promise<string>;
|
|
729
|
+
getCommitHash(ref?: string): Promise<string>;
|
|
730
|
+
setConfig(key: string, value: string, scope?: 'local' | 'global' | 'system'): Promise<void>;
|
|
731
|
+
getMergeBase(branchA: string, branchB: string): Promise<string>;
|
|
732
|
+
getChangedFiles(fromCommit: string, toCommit: string, pathFilter: string): Promise<ChangedFile[]>;
|
|
733
|
+
getStagedFiles(): Promise<string[]>;
|
|
734
|
+
getFileContent(commitHash: string, filePath: string): Promise<string>;
|
|
735
|
+
getCommitHistory(branch: string, options?: GetCommitHistoryOptions): Promise<CommitInfo[]>;
|
|
736
|
+
getCommitHistoryRange(fromHash: string, toHash: string, options?: GetCommitHistoryOptions): Promise<CommitInfo[]>;
|
|
737
|
+
getCommitMessage(commitHash: string): Promise<string>;
|
|
738
|
+
hasUncommittedChanges(pathFilter?: string): Promise<boolean>;
|
|
739
|
+
isRebaseInProgress(): Promise<boolean>;
|
|
740
|
+
branchExists(branchName: string): Promise<boolean>;
|
|
741
|
+
listRemoteBranches(remoteName: string): Promise<string[]>;
|
|
742
|
+
isRemoteConfigured(remoteName: string): Promise<boolean>;
|
|
743
|
+
getBranchRemote(branchName: string): Promise<string | null>;
|
|
744
|
+
getConflictedFiles(): Promise<string[]>;
|
|
745
|
+
checkoutBranch(branchName: string): Promise<void>;
|
|
746
|
+
stash(message?: string): Promise<string | null>;
|
|
747
|
+
stashPop(): Promise<boolean>;
|
|
748
|
+
stashDrop(stashHash?: string): Promise<void>;
|
|
749
|
+
checkoutOrphanBranch(branchName: string): Promise<void>;
|
|
750
|
+
fetch(remote: string): Promise<void>;
|
|
751
|
+
pull(remote: string, branchName: string): Promise<void>;
|
|
752
|
+
pullRebase(remote: string, branchName: string): Promise<void>;
|
|
753
|
+
resetHard(target: string): Promise<void>;
|
|
754
|
+
checkoutFilesFromBranch(sourceBranch: string, filePaths: string[]): Promise<void>;
|
|
755
|
+
add(filePaths: string[], options?: {
|
|
756
|
+
force?: boolean;
|
|
757
|
+
}): Promise<void>;
|
|
758
|
+
rm(filePaths: string[]): Promise<void>;
|
|
759
|
+
commit(message: string, author?: CommitAuthor): Promise<string>;
|
|
760
|
+
commitAllowEmpty(message: string, author?: CommitAuthor): Promise<string>;
|
|
761
|
+
push(remote: string, branchName: string): Promise<void>;
|
|
762
|
+
pushWithUpstream(remote: string, branchName: string): Promise<void>;
|
|
763
|
+
setUpstream(branchName: string, remote: string, remoteBranch: string): Promise<void>;
|
|
764
|
+
rebaseContinue(): Promise<string>;
|
|
765
|
+
rebaseAbort(): Promise<void>;
|
|
766
|
+
createBranch(branchName: string, startPoint?: string): Promise<void>;
|
|
767
|
+
rebase(targetBranch: string): Promise<void>;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
type index_BranchAlreadyExistsError = BranchAlreadyExistsError;
|
|
771
|
+
declare const index_BranchAlreadyExistsError: typeof BranchAlreadyExistsError;
|
|
772
|
+
type index_BranchNotFoundError = BranchNotFoundError;
|
|
773
|
+
declare const index_BranchNotFoundError: typeof BranchNotFoundError;
|
|
774
|
+
type index_ChangedFile = ChangedFile;
|
|
775
|
+
type index_CommitAuthor = CommitAuthor;
|
|
776
|
+
type index_CommitInfo = CommitInfo;
|
|
777
|
+
type index_ExecOptions = ExecOptions;
|
|
778
|
+
type index_ExecResult = ExecResult;
|
|
779
|
+
type index_FileNotFoundError = FileNotFoundError;
|
|
780
|
+
declare const index_FileNotFoundError: typeof FileNotFoundError;
|
|
781
|
+
type index_GetCommitHistoryOptions = GetCommitHistoryOptions;
|
|
782
|
+
type index_GitCommandError = GitCommandError;
|
|
783
|
+
declare const index_GitCommandError: typeof GitCommandError;
|
|
784
|
+
type index_GitError = GitError;
|
|
785
|
+
declare const index_GitError: typeof GitError;
|
|
786
|
+
type index_GitModuleDependencies = GitModuleDependencies;
|
|
787
|
+
type index_IGitModule = IGitModule;
|
|
788
|
+
type index_MergeConflictError = MergeConflictError;
|
|
789
|
+
declare const index_MergeConflictError: typeof MergeConflictError;
|
|
790
|
+
type index_RebaseConflictError = RebaseConflictError;
|
|
791
|
+
declare const index_RebaseConflictError: typeof RebaseConflictError;
|
|
792
|
+
type index_RebaseNotInProgressError = RebaseNotInProgressError;
|
|
793
|
+
declare const index_RebaseNotInProgressError: typeof RebaseNotInProgressError;
|
|
794
|
+
declare namespace index {
|
|
795
|
+
export { index_BranchAlreadyExistsError as BranchAlreadyExistsError, index_BranchNotFoundError as BranchNotFoundError, type index_ChangedFile as ChangedFile, type index_CommitAuthor as CommitAuthor, type index_CommitInfo as CommitInfo, type index_ExecOptions as ExecOptions, type index_ExecResult as ExecResult, index_FileNotFoundError as FileNotFoundError, type index_GetCommitHistoryOptions as GetCommitHistoryOptions, index_GitCommandError as GitCommandError, index_GitError as GitError, type index_GitModuleDependencies as GitModuleDependencies, type index_IGitModule as IGitModule, index_MergeConflictError as MergeConflictError, index_RebaseConflictError as RebaseConflictError, index_RebaseNotInProgressError as RebaseNotInProgressError };
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
export { type ActorState as A, type ConfigStore as C, type ExecOptions as E, type FsFileListerOptions as F, type GitGovConfig as G, type IGitModule as I, type KeyProvider as K, type MemoryFileListerOptions as M, type RecordStore as R, type SessionStore as S, type GitGovSession as a, type GitModuleDependencies as b, type ExecResult as c, type ChangedFile as d, type GetCommitHistoryOptions as e, type CommitInfo as f, type CommitAuthor as g, type ISessionManager as h, type SyncPreferencesUpdate as i, type SyncStatus as j, type AuditState as k, type AuditStateUpdate as l, type IConfigManager as m, type SyncConfig as n, type SyncDefaults as o, KeyProviderError as p, type KeyProviderErrorCode as q, type FileListOptions as r, type FileLister as s, type FileStats as t, index as u };
|