kith-coord 0.0.0-stage → 0.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/CODE_OF_CONDUCT.md +5 -0
  3. package/CONTRIBUTING.md +47 -0
  4. package/LICENSE +21 -0
  5. package/README.md +143 -2
  6. package/SECURITY.md +13 -0
  7. package/assets/brand/avatar.png +0 -0
  8. package/assets/brand/avatar.svg +1 -0
  9. package/assets/brand/lockup.png +0 -0
  10. package/assets/brand/lockup.svg +1 -0
  11. package/assets/brand/mark.svg +1 -0
  12. package/assets/brand/readme-header.png +0 -0
  13. package/assets/brand/readme-header.svg +1 -0
  14. package/assets/brand/social-preview.png +0 -0
  15. package/assets/brand/social-preview.svg +1 -0
  16. package/assets/brand/wordmark.png +0 -0
  17. package/assets/brand/wordmark.svg +1 -0
  18. package/dist/cli/index.d.ts +1 -0
  19. package/dist/cli/index.js +5022 -0
  20. package/dist/cli/index.js.map +1 -0
  21. package/dist/command-worker.d.ts +2 -0
  22. package/dist/command-worker.js +30 -0
  23. package/dist/command-worker.js.map +1 -0
  24. package/dist/index.d.ts +983 -0
  25. package/dist/index.js +3708 -0
  26. package/dist/index.js.map +1 -0
  27. package/docs/architecture.md +37 -0
  28. package/docs/client-validation.md +51 -0
  29. package/docs/integrations.md +75 -0
  30. package/docs/path-and-scope-rules.md +45 -0
  31. package/docs/protocol/tools.v1.json +425 -0
  32. package/docs/protocol.md +35 -0
  33. package/docs/reliability.md +78 -0
  34. package/docs/roadmap.md +42 -0
  35. package/docs/sessions-and-mutexes.md +97 -0
  36. package/docs/usage.md +101 -0
  37. package/docs/validation/2026-10-19-claude-client-report.json +67 -0
  38. package/docs/validation/2026-10-19-claude-hook-report.json +33 -0
  39. package/docs/validation/2026-10-19-claude-hook-unavailable-report.json +20 -0
  40. package/docs/validation/2026-10-19-claude-mutex-report.json +34 -0
  41. package/docs/validation/2026-10-19-codex-client-report.json +55 -0
  42. package/docs/validation/2026-10-19-codex-mutex-report.json +33 -0
  43. package/docs/validation/2026-10-19-path-hardening-claude.json +32 -0
  44. package/docs/validation/2026-10-19-path-hardening-codex.json +30 -0
  45. package/docs/validation/2026-10-19-recovery-claude.json +35 -0
  46. package/docs/validation/2026-10-19-recovery-codex.json +33 -0
  47. package/docs/validation/2026-10-19-sqlite-runtime-report.json +50 -0
  48. package/docs/validation/2026-10-20-adoption-claude.json +35 -0
  49. package/docs/validation/2026-10-20-adoption-codex-first-attempt.json +20 -0
  50. package/docs/validation/2026-10-20-adoption-codex.json +73 -0
  51. package/docs/validation/2026-10-20-adoption-hook-failure.json +18 -0
  52. package/docs/validation/2026-10-20-subtraction-claude.json +35 -0
  53. package/docs/validation/2026-10-20-subtraction-codex.json +33 -0
  54. package/package.json +83 -4
@@ -0,0 +1,983 @@
1
+ import * as node_sqlite from 'node:sqlite';
2
+ import { DatabaseSync } from 'node:sqlite';
3
+
4
+ interface CoordEvent {
5
+ id: number;
6
+ timestamp: number;
7
+ agent_id: string | null;
8
+ event_type: string;
9
+ payload: Record<string, unknown>;
10
+ }
11
+ declare class CoordDatabase {
12
+ readonly db: DatabaseSync;
13
+ readonly repoRoot: string;
14
+ readonly commonGitDir: string | null;
15
+ readonly isLinkedWorktree: boolean;
16
+ readonly coordDir: string;
17
+ readonly dbPath: string;
18
+ private inTransaction;
19
+ constructor(repoRoot: string, customDbPath?: string);
20
+ /** Validate an existing snapshot without migration or ownership changes. */
21
+ static inspectSchema(db: DatabaseSync): number;
22
+ private configurePragmas;
23
+ private static schemaVersion;
24
+ private static fencingEpoch;
25
+ private migrate;
26
+ /**
27
+ * Executes a synchronous callback inside a `BEGIN IMMEDIATE` transaction
28
+ * with automatic jittered backoff retries if another process temporarily holds the WAL write lock.
29
+ */
30
+ withTransaction<T>(fn: () => T, maxRetries?: number): T;
31
+ /**
32
+ * Atomically increments and returns the next monotonic fencing token.
33
+ */
34
+ nextFencingToken(): number;
35
+ currentFencingEpoch(): number;
36
+ logEvent(agentId: string | null, eventType: string, payload?: Record<string, unknown>): number;
37
+ getEventsSince(sinceId: number, limit?: number): CoordEvent[];
38
+ close(): void;
39
+ }
40
+
41
+ interface AgentRecord {
42
+ id: string;
43
+ name: string;
44
+ client: string;
45
+ pid: number;
46
+ pid_start_time: string;
47
+ pgid: number;
48
+ worktree_path: string | null;
49
+ branch: string | null;
50
+ shadow_tree_sha: string | null;
51
+ status: 'active' | 'idle' | 'dead' | 'completed';
52
+ last_seen_event_id: number;
53
+ registered_at: number;
54
+ last_heartbeat_at: number;
55
+ lease_expires_at: number;
56
+ }
57
+ declare class SessionOwnershipError extends Error {
58
+ constructor(agentId: string);
59
+ }
60
+ declare class StaleFencingTokenError extends Error {
61
+ readonly resourceId: string;
62
+ readonly providedToken: number;
63
+ readonly expectedToken: number;
64
+ constructor(resourceId: string, providedToken: number, expectedToken: number);
65
+ }
66
+ interface SessionRegistration {
67
+ agent: AgentRecord;
68
+ fencingToken: number;
69
+ sessionToken: string;
70
+ sessionEpoch: number;
71
+ }
72
+ declare class FencingAndAgentManager {
73
+ private readonly coordDb;
74
+ static readonly DEFAULT_LEASE_MS: number;
75
+ private readonly capabilities;
76
+ constructor(coordDb: CoordDatabase);
77
+ static validateLease(duration: number): number;
78
+ /** A real kernel process identity; tests must not supply liveness sentinels. */
79
+ static getProcessStartTime(pid: number): string | null;
80
+ static isProcessAlive(pid: number, expectedStartTime: string): boolean;
81
+ registerAgent(params: {
82
+ id: string;
83
+ name?: string;
84
+ client?: string;
85
+ pid?: number;
86
+ pgid?: number;
87
+ worktreePath?: string | null;
88
+ branch?: string | null;
89
+ leaseDurationMs?: number;
90
+ sessionToken?: string;
91
+ }): SessionRegistration;
92
+ resumeSession(agentId: string, sessionToken: string): number;
93
+ assertSession(agentId: string, sessionToken?: string | undefined): number;
94
+ sessionEnvironment(agentId: string): NodeJS.ProcessEnv;
95
+ heartbeat(agentId: string, leaseDurationMs?: number): AgentRecord;
96
+ getAgent(agentId: string): AgentRecord | null;
97
+ listAgents(onlyActive?: boolean): AgentRecord[];
98
+ reapDeadAgents(): string[];
99
+ completeAgentSession(agentId: string): void;
100
+ abandonAgentSession(agentId: string): void;
101
+ private reclaim;
102
+ verifyFencingToken(resourceId: string, provided: number, expected: number): void;
103
+ private hash;
104
+ }
105
+
106
+ interface SpawnedWorktree {
107
+ agentId: string;
108
+ worktreePath: string;
109
+ branch: string;
110
+ hydrationMethod: 'apfs-cow' | 'reflink-cow' | 'copy' | 'none';
111
+ hydratedDirs: string[];
112
+ durationMs: number;
113
+ }
114
+ declare class CoWWorktreeManager {
115
+ private readonly coordDb;
116
+ private readonly fencing;
117
+ private static readonly HYDRATABLE_DIRS;
118
+ private static readonly ENV_FILES;
119
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager);
120
+ /**
121
+ * Spawns an isolated Git worktree for `agentId` and hydrates `node_modules` / `.env`
122
+ * using APFS Copy-on-Write (`cp -cR`) on macOS or reflink on Linux (with independent-copy fallback).
123
+ */
124
+ spawnWorktree(params: {
125
+ agentId: string;
126
+ branch?: string;
127
+ baseRef?: string;
128
+ }): SpawnedWorktree;
129
+ private cloneDirectoryCoW;
130
+ removeWorktree(agentId: string): boolean;
131
+ listWorktrees(): Array<{
132
+ path: string;
133
+ head: string;
134
+ branch: string | null;
135
+ }>;
136
+ }
137
+
138
+ interface WorktreeChange {
139
+ status: string;
140
+ path: string;
141
+ originalPath?: string;
142
+ }
143
+ declare function worktreeChanges(cwd: string): WorktreeChange[];
144
+ interface WorkspaceObservation {
145
+ agentId: string;
146
+ path: string;
147
+ recordedBranch: string | null;
148
+ status: AgentRecord['status'];
149
+ leaseExpired: boolean;
150
+ lastHeartbeatAt: number;
151
+ available: boolean;
152
+ error?: string;
153
+ branch: string | null;
154
+ head: string | null;
155
+ comparisonBase: string | null;
156
+ dirtyFiles: WorktreeChange[];
157
+ lastCommitAt: number | null;
158
+ hoursSinceLastCommit: number | null;
159
+ ahead: number | null;
160
+ behind: number | null;
161
+ overlaps: Array<{
162
+ path: string;
163
+ agentIds: string[];
164
+ }>;
165
+ }
166
+ /** Git observation never stages files, checks out branches, fetches, or refreshes the index. */
167
+ declare function observeWorkspaces(repoRoot: string, agents: AgentRecord[], now?: number): WorkspaceObservation[];
168
+ /** Preview committed inputs only. merge-tree may write unreachable Git objects, never worktree/index/database contents. */
169
+ declare function previewIntegration(repoRoot: string, agent: AgentRecord): {
170
+ ok: boolean;
171
+ clean: null;
172
+ sourceHead: string;
173
+ targetHead: string;
174
+ sourceBranch: string;
175
+ targetBranch: string;
176
+ conflicts: never[];
177
+ dirtyFiles: WorktreeChange[];
178
+ targetDirtyFiles: WorktreeChange[];
179
+ reason: string;
180
+ verified?: undefined;
181
+ } | {
182
+ ok: boolean;
183
+ clean: boolean;
184
+ sourceHead: string;
185
+ targetHead: string;
186
+ sourceBranch: string;
187
+ targetBranch: string;
188
+ conflicts: string[];
189
+ dirtyFiles: WorktreeChange[];
190
+ targetDirtyFiles: WorktreeChange[];
191
+ verified: boolean;
192
+ reason?: undefined;
193
+ };
194
+
195
+ type SymbolKind = 'function' | 'type' | 'interface' | 'class' | 'schema' | 'route' | 'const';
196
+ interface ExtractedSymbol {
197
+ symbolName: string;
198
+ kind: SymbolKind;
199
+ signature: string;
200
+ astHash: string;
201
+ paramsFingerprint: string;
202
+ docComment: string;
203
+ }
204
+ interface ExtractedImport {
205
+ rawSpecifier: string;
206
+ resolvedPath: string | null;
207
+ importedSymbols: string[];
208
+ }
209
+ interface FileAstAnalysis {
210
+ filePath: string;
211
+ fileHash: string;
212
+ exports: ExtractedSymbol[];
213
+ imports: ExtractedImport[];
214
+ }
215
+ declare class AstAnalyzer {
216
+ /**
217
+ * Analyzes a source file's content to extract exported contracts (functions, types,
218
+ * interfaces, schemas, routes) and imported module dependencies.
219
+ */
220
+ static analyzeSource(repoRoot: string, filePath: string, sourceContent?: string): FileAstAnalysis;
221
+ static extractExports(content: string): ExtractedSymbol[];
222
+ static extractImports(repoRoot: string, sourceRelPath: string, content: string): ExtractedImport[];
223
+ static resolveRelativeImport(repoRoot: string, sourceRelPath: string, specifier: string): string | null;
224
+ private static extractBracedBlockSummary;
225
+ private static extractFieldTypesFingerprint;
226
+ static computeParamsFingerprint(rawParams: string, rawReturn: string): string;
227
+ private static normalizeWhitespace;
228
+ private static hashSignature;
229
+ }
230
+
231
+ interface LockRecord {
232
+ id: string;
233
+ pattern: string;
234
+ lock_type: 'glob' | 'file' | 'symbol';
235
+ mode: 'exclusive' | 'shared';
236
+ owner_agent_id: string;
237
+ task_id: string | null;
238
+ fencing_token: number;
239
+ reason: string;
240
+ acquired_at: number;
241
+ expires_at: number;
242
+ }
243
+ interface LockConflict {
244
+ existingLock: LockRecord;
245
+ requestedPattern: string;
246
+ ownerAgentName: string;
247
+ ownerIntent: string | null;
248
+ }
249
+ interface AcquireLockResult {
250
+ ok: boolean;
251
+ fencingToken: number;
252
+ locks: LockRecord[];
253
+ conflicts: LockConflict[];
254
+ }
255
+ declare class LockEngine {
256
+ private readonly coordDb;
257
+ private readonly fencing;
258
+ private readonly pathCase;
259
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager);
260
+ static normalizePattern(repoRoot: string, rawPattern: string): string;
261
+ static normalizeFile(repoRoot: string, file: string): string;
262
+ private static literalScope;
263
+ private rootForAgent;
264
+ private wildcardHasAliases;
265
+ /** Exact overlap for the documented scope grammar; legacy unsupported locks block conservatively. */
266
+ static patternsOverlap(rawA: string, rawB: string): boolean;
267
+ /**
268
+ * Atomically acquires locks on one or more file/glob/symbol patterns.
269
+ * All-or-nothing: if any pattern conflicts with another live agent, no locks are created.
270
+ */
271
+ acquireLocks(params: {
272
+ agentId: string;
273
+ patterns: string[];
274
+ mode?: 'exclusive' | 'shared';
275
+ lockType?: 'glob' | 'file' | 'symbol';
276
+ taskId?: string | null;
277
+ reason?: string;
278
+ leaseDurationMs?: number;
279
+ }): AcquireLockResult;
280
+ /**
281
+ * Checks whether `agentId` is allowed to edit `filePath`.
282
+ * Also verifies the fencing token if provided.
283
+ */
284
+ checkFileWriteAccess(params: {
285
+ agentId: string;
286
+ filePath: string;
287
+ fencingToken?: number;
288
+ }): {
289
+ allowed: boolean;
290
+ reason?: string;
291
+ conflictingLock?: LockRecord;
292
+ ownerIntent?: string | null;
293
+ };
294
+ releaseLocks(params: {
295
+ agentId: string;
296
+ patterns?: string[];
297
+ fencingToken?: number;
298
+ }): number;
299
+ private overlapsExisting;
300
+ listLocks(): LockRecord[];
301
+ }
302
+
303
+ interface ContractRecord {
304
+ id: string;
305
+ file_path: string;
306
+ symbol_name: string;
307
+ kind: SymbolKind;
308
+ signature: string;
309
+ ast_hash: string;
310
+ params_fingerprint: string;
311
+ doc_comment: string;
312
+ owner_agent_id: string | null;
313
+ version: number;
314
+ is_breaking: boolean;
315
+ updated_at: number;
316
+ }
317
+ interface BlastRadiusAlert {
318
+ modifiedFile: string;
319
+ symbolName: string;
320
+ previousSignature: string;
321
+ newSignature: string | null;
322
+ affectedDownstreamFile: string;
323
+ hopDistance: number;
324
+ affectedAgentId: string | null;
325
+ }
326
+ interface FileModificationReport {
327
+ filePath: string;
328
+ upsertedContracts: ContractRecord[];
329
+ removedSymbols: string[];
330
+ breakingChanges: BlastRadiusAlert[];
331
+ transitiveDependents: Array<{
332
+ filePath: string;
333
+ hopDistance: number;
334
+ }>;
335
+ }
336
+ declare class DependencyAndContractEngine {
337
+ private readonly coordDb;
338
+ private readonly lockEngine;
339
+ private readonly fencing;
340
+ constructor(coordDb: CoordDatabase, lockEngine: LockEngine, fencing: FencingAndAgentManager);
341
+ /**
342
+ * Scans a repository directory to index initial file dependencies and exported contracts.
343
+ */
344
+ indexRepositoryFiles(dirPath?: string): number;
345
+ private walkSourceFiles;
346
+ /**
347
+ * Automatically parses a modified file's imports and exports, updates the dependency graph
348
+ * and Contract Blackboard, and calculates the transitive blast radius
349
+ * if any exported signature changed or was removed.
350
+ */
351
+ recordFileModification(agentId: string | null, rawFilePath: string, sourceContent?: string): FileModificationReport;
352
+ /**
353
+ * Explicitly publishes a contract to the shared blackboard (e.g. REST route, env var, or type).
354
+ */
355
+ publishExplicitContract(params: {
356
+ agentId: string;
357
+ filePath: string;
358
+ symbolName: string;
359
+ kind: SymbolKind;
360
+ signature: string;
361
+ docComment?: string;
362
+ }): ContractRecord;
363
+ private upsertContractInternal;
364
+ /**
365
+ * Computes all files that directly or transitively import `targetFile` up to `maxHops` away.
366
+ */
367
+ getTransitiveDependents(targetFile: string, maxHops?: number): Array<{
368
+ filePath: string;
369
+ hopDistance: number;
370
+ importedSymbols: string[];
371
+ }>;
372
+ listContracts(filePathFilter?: string): ContractRecord[];
373
+ private mapRowToContract;
374
+ }
375
+
376
+ interface ConflictRecord {
377
+ id: string;
378
+ agent_a: string;
379
+ agent_b: string;
380
+ file_path: string;
381
+ severity: 'text_conflict' | 'transitive_contract_break';
382
+ details: {
383
+ reason: string;
384
+ baseBlob?: string;
385
+ blobA?: string;
386
+ blobB?: string;
387
+ };
388
+ detected_at: number;
389
+ }
390
+ interface DirtyMergeProbeResult {
391
+ clean: boolean;
392
+ mergedTreeSha: string | null;
393
+ conflicts: ConflictRecord[];
394
+ }
395
+ declare class ShadowGitEngine {
396
+ private readonly coordDb;
397
+ private readonly fencing;
398
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager);
399
+ isGitRepository(dir?: string): boolean;
400
+ getHeadCommit(dir?: string): string | null;
401
+ private getShadowIndexPath;
402
+ /**
403
+ * Updates an agent's ephemeral shadow Git index (`.coord/shadow-index/<agent-id>.index`)
404
+ * without touching the repository's real `.git/index`, and creates a synthetic shadow
405
+ * commit object in `.git/objects` so `git merge-tree --write-tree` can run 3-way merges
406
+ * across uncommitted files in <15ms.
407
+ */
408
+ updateAgentShadowTree(params: {
409
+ agentId: string;
410
+ modifiedFiles?: Array<{
411
+ filePath: string;
412
+ content?: string;
413
+ }>;
414
+ worktreeDir?: string;
415
+ }): string | null;
416
+ /**
417
+ * Runs `git merge-tree --write-tree` across `agentId`'s dirty shadow commit and every
418
+ * other active agent's dirty shadow commit (or branch).
419
+ */
420
+ probeAllActiveConflicts(agentId: string, modifiedFiles?: Array<{
421
+ filePath: string;
422
+ content?: string;
423
+ }>, worktreeDir?: string): DirtyMergeProbeResult;
424
+ probePairConflict(agentA: string, commitA: string, agentB: string, commitB: string): DirtyMergeProbeResult;
425
+ listConflicts(): ConflictRecord[];
426
+ }
427
+
428
+ interface FileSnapshotEntry {
429
+ relPath: string;
430
+ mtimeMs: number;
431
+ size: number;
432
+ sha256: string;
433
+ lockedByOther: boolean;
434
+ backupContentBase64?: string;
435
+ }
436
+ interface QuarantineRecord {
437
+ id: string;
438
+ agent_id: string;
439
+ command: string;
440
+ file_path: string;
441
+ patch_path: string;
442
+ reason: string;
443
+ created_at: number;
444
+ }
445
+ interface BashGuardPostReport {
446
+ allowed: boolean;
447
+ authorizedModifiedFiles: string[];
448
+ quarantinedViolations: QuarantineRecord[];
449
+ }
450
+ declare class BashMerkleGuard {
451
+ private readonly coordDb;
452
+ private readonly fencing;
453
+ private readonly lockEngine;
454
+ private readonly depGraph;
455
+ private readonly shadowGit;
456
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager, lockEngine: LockEngine, depGraph: DependencyAndContractEngine, shadowGit: ShadowGitEngine);
457
+ /**
458
+ * Checks whether a shell command is safe to execute in the workspace.
459
+ */
460
+ checkCommandSafety(params: {
461
+ agentId: string;
462
+ command: string;
463
+ inIsolatedWorktree?: boolean;
464
+ }): {
465
+ safe: boolean;
466
+ reason?: string;
467
+ };
468
+ private getSnapshotFilePath;
469
+ /**
470
+ * Captures a Merkle snapshot of workspace files before a Bash tool execution.
471
+ * For any file locked by another active agent, stores a full lossless backup so
472
+ * unauthorized mutations by bash scripts (`sed`, `python`, etc.) can be reverted atomically.
473
+ */
474
+ capturePreBashSnapshot(agentId: string, rootDir?: string): string;
475
+ /**
476
+ * Compares workspace state after a Bash command completes against the pre-Bash Merkle snapshot.
477
+ * Saves recovery copies of edits to files locked by sibling agents. Restoration is opt-in,
478
+ * and indexes authorized modifications into the AST Contract Blackboard & Dirty-Tree Conflict Radar.
479
+ */
480
+ verifyPostBashAndQuarantine(params: {
481
+ agentId: string;
482
+ command: string;
483
+ rootDir?: string;
484
+ restoreLockedFiles?: boolean;
485
+ }): BashGuardPostReport;
486
+ private quarantineAndRevertFile;
487
+ private walkWorkspaceFiles;
488
+ listQuarantined(): QuarantineRecord[];
489
+ }
490
+
491
+ interface MergeTrainEntry {
492
+ id: string;
493
+ agent_id: string;
494
+ branch: string;
495
+ worktree_path: string | null;
496
+ status: 'queued' | 'testing' | 'merged' | 'failed';
497
+ fencing_token: number;
498
+ verification_cmd: string | null;
499
+ diagnostics_output: string | null;
500
+ created_at: number;
501
+ updated_at: number;
502
+ }
503
+ interface SpeculativeMergeResult {
504
+ merged: boolean;
505
+ entry: MergeTrainEntry;
506
+ mergedCommitSha: string | null;
507
+ diagnostics: string;
508
+ }
509
+ declare class SpeculativeMergeTrain {
510
+ private readonly coordDb;
511
+ private readonly fencing;
512
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager);
513
+ /**
514
+ * Enqueues and executes a Bors-style speculative integration test in an isolated staging
515
+ * worktree before advancing the main repository branch.
516
+ * Refuses Git conflicts and runs `verificationCmd` (e.g. `tsc --noEmit` or `npm test`) before fast-forwarding `main`.
517
+ */
518
+ enqueueAndMerge(params: {
519
+ agentId: string;
520
+ branch: string;
521
+ worktreePath?: string | null;
522
+ verificationCmd?: string | null;
523
+ commitMessage?: string;
524
+ }): SpeculativeMergeResult;
525
+ private gitHead;
526
+ private gitBranch;
527
+ private requireCleanTarget;
528
+ private cleanupStageWorktree;
529
+ getEntry(id: string): MergeTrainEntry | null;
530
+ listQueue(): MergeTrainEntry[];
531
+ }
532
+
533
+ interface ResourceRecord {
534
+ id: string;
535
+ type: 'port' | 'mutex';
536
+ name: string;
537
+ value: string;
538
+ owner_agent_id: string;
539
+ fencing_token: number;
540
+ queue: string[];
541
+ acquired_at: number;
542
+ expires_at: number;
543
+ }
544
+ declare class ResourceBroker {
545
+ private readonly coordDb;
546
+ private readonly fencing;
547
+ private activeExecutions;
548
+ hasActiveCommands(): boolean;
549
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager);
550
+ /**
551
+ * Acquires a collision-free port lease for `(agentId, serviceName)`.
552
+ * Verifies both SQLite resource table and OS TCP socket availability.
553
+ */
554
+ acquirePort(params: {
555
+ agentId: string;
556
+ serviceName: string;
557
+ basePort?: number;
558
+ leaseDurationMs?: number;
559
+ }): Promise<{
560
+ port: number;
561
+ fencingToken: number;
562
+ resource: ResourceRecord;
563
+ }>;
564
+ static isTcpPortFree(port: number): Promise<boolean>;
565
+ /** FIFO order survives releases; queued requests belong to a specific session epoch. */
566
+ tryAcquireMutex(params: {
567
+ agentId: string;
568
+ mutexName: string;
569
+ leaseDurationMs?: number;
570
+ requestId?: string;
571
+ }): {
572
+ acquired: boolean;
573
+ fencingToken: number;
574
+ holderAgentId: string;
575
+ queuePosition: number;
576
+ };
577
+ renewMutex(params: {
578
+ agentId: string;
579
+ mutexName: string;
580
+ fencingToken: number;
581
+ leaseDurationMs?: number;
582
+ }): void;
583
+ releaseMutex(params: {
584
+ agentId: string;
585
+ mutexName: string;
586
+ fencingToken: number;
587
+ }): boolean;
588
+ /** Renew leases while a detached, recorded process group runs; stop it before releasing. */
589
+ executeWithMutex(params: {
590
+ agentId: string;
591
+ mutexName: string;
592
+ command: string | string[];
593
+ cwd?: string;
594
+ timeoutMs?: number;
595
+ commandTimeoutMs?: number;
596
+ leaseDurationMs?: number;
597
+ killGraceMs?: number;
598
+ signal?: AbortSignal;
599
+ maxOutputBytes?: number;
600
+ onStdout?: (chunk: Buffer) => void;
601
+ onStderr?: (chunk: Buffer) => void;
602
+ }): Promise<{
603
+ stdout: string;
604
+ stderr: string;
605
+ exitCode: number;
606
+ waitedMs: number;
607
+ }>;
608
+ private getRun;
609
+ private runIsAlive;
610
+ private clearRun;
611
+ private waiters;
612
+ private pruneWaiters;
613
+ getResource(type: 'port' | 'mutex', name: string): ResourceRecord | null;
614
+ listResources(): ResourceRecord[];
615
+ private mapRow;
616
+ }
617
+
618
+ interface TaskRecord {
619
+ id: string;
620
+ title: string;
621
+ intent_summary: string;
622
+ status: 'queued' | 'active' | 'done' | 'blocked';
623
+ priority: number;
624
+ owner_agent_id: string | null;
625
+ fencing_token: number | null;
626
+ depends_on: string[];
627
+ scope_globs: string[];
628
+ created_at: number;
629
+ updated_at: number;
630
+ }
631
+ interface DeclareIntentResult {
632
+ ok: boolean;
633
+ task: TaskRecord | null;
634
+ fencingToken: number;
635
+ locks: LockRecord[];
636
+ lockConflicts: LockConflict[];
637
+ activeSiblingIntents: TaskRecord[];
638
+ }
639
+ declare class IntentAndTaskEngine {
640
+ private readonly coordDb;
641
+ private readonly fencing;
642
+ private readonly lockEngine;
643
+ constructor(coordDb: CoordDatabase, fencing: FencingAndAgentManager, lockEngine: LockEngine);
644
+ /**
645
+ * Peer-to-Peer Mode: Declares an agent's intent, checks scope-lock collisions
646
+ * and reserves the scope if available.
647
+ */
648
+ declareIntent(params: {
649
+ agentId: string;
650
+ title: string;
651
+ intentSummary?: string;
652
+ scopeGlobs: string[];
653
+ }): DeclareIntentResult;
654
+ /**
655
+ * Orchestrator Mode: Adds a task to the DAG queue with optional dependencies and priority.
656
+ */
657
+ addTask(params: {
658
+ id?: string;
659
+ title: string;
660
+ intentSummary?: string;
661
+ priority?: number;
662
+ dependsOn?: string[];
663
+ scopeGlobs?: string[];
664
+ }): TaskRecord;
665
+ private hasPathInDag;
666
+ /**
667
+ * Orchestrator Mode: Atomically claims the highest-priority unblocked task whose scope locks are available.
668
+ */
669
+ claimNextTask(agentId: string): {
670
+ claimed: boolean;
671
+ task: TaskRecord | null;
672
+ fencingToken: number | null;
673
+ locks: LockRecord[];
674
+ reason?: string;
675
+ };
676
+ completeTask(params: {
677
+ agentId: string;
678
+ taskId?: string;
679
+ fencingToken?: number;
680
+ releaseLocks?: boolean;
681
+ }): TaskRecord[];
682
+ getTask(taskId: string): TaskRecord | null;
683
+ listTasks(filter?: {
684
+ status?: TaskRecord['status'];
685
+ }): TaskRecord[];
686
+ }
687
+
688
+ interface AgentUnreadDelta {
689
+ events: CoordEvent[];
690
+ activeConflicts: ConflictRecord[];
691
+ formattedFooter: string;
692
+ }
693
+ interface PostFileEditHookResult {
694
+ filePath: string;
695
+ contractReport: FileModificationReport;
696
+ dirtyMergeConflicts: ConflictRecord[];
697
+ warnings: string[];
698
+ }
699
+ declare class KithEngine {
700
+ readonly coordDb: CoordDatabase;
701
+ readonly fencing: FencingAndAgentManager;
702
+ readonly locks: LockEngine;
703
+ readonly intents: IntentAndTaskEngine;
704
+ readonly depGraph: DependencyAndContractEngine;
705
+ readonly shadowGit: ShadowGitEngine;
706
+ readonly worktrees: CoWWorktreeManager;
707
+ readonly mergeTrain: SpeculativeMergeTrain;
708
+ readonly bashGuard: BashMerkleGuard;
709
+ readonly broker: ResourceBroker;
710
+ constructor(repoRoot?: string, customDbPath?: string);
711
+ /**
712
+ * Executes the complete PostToolUse pipeline whenever an agent writes or edits a file:
713
+ * 1. Extracts AST exports/imports and updates the Contract Blackboard & Import Graph
714
+ * 2. Computes transitive breaking-change blast radius across downstream dependent files
715
+ * 3. Updates the agent's shadow Git index (`GIT_INDEX_FILE`) and runs `git merge-tree` against sibling dirty trees
716
+ */
717
+ processPostFileEdit(params: {
718
+ agentId: string;
719
+ filePath: string;
720
+ content?: string;
721
+ worktreeDir?: string;
722
+ }): PostFileEditHookResult;
723
+ /**
724
+ * Consumes unread coordination events and active conflicts for `agentId` since its last tool call
725
+ * and formats a concise context-delta footer to append to MCP/CLI responses.
726
+ */
727
+ consumeAgentDelta(agentId: string): AgentUnreadDelta;
728
+ getStatus(): {
729
+ protocolVersion: string;
730
+ repository: {
731
+ root: string;
732
+ commonGitDir: string | null;
733
+ coordDir: string;
734
+ };
735
+ runtime: {
736
+ node: string;
737
+ };
738
+ fencingEpoch: number;
739
+ agents: AgentRecord[];
740
+ locks: LockRecord[];
741
+ tasks: TaskRecord[];
742
+ conflicts: ConflictRecord[];
743
+ contracts: ContractRecord[];
744
+ resources: ResourceRecord[];
745
+ mergeQueue: MergeTrainEntry[];
746
+ quarantined: QuarantineRecord[];
747
+ mutexWaiters: Record<string, node_sqlite.SQLOutputValue>[];
748
+ commandGuards: Record<string, node_sqlite.SQLOutputValue>[];
749
+ workspaces: WorkspaceObservation[];
750
+ };
751
+ previewIntegration(agentId: string): {
752
+ ok: boolean;
753
+ clean: null;
754
+ sourceHead: string;
755
+ targetHead: string;
756
+ sourceBranch: string;
757
+ targetBranch: string;
758
+ conflicts: never[];
759
+ dirtyFiles: WorktreeChange[];
760
+ targetDirtyFiles: WorktreeChange[];
761
+ reason: string;
762
+ verified?: undefined;
763
+ } | {
764
+ ok: boolean;
765
+ clean: boolean;
766
+ sourceHead: string;
767
+ targetHead: string;
768
+ sourceBranch: string;
769
+ targetBranch: string;
770
+ conflicts: string[];
771
+ dirtyFiles: WorktreeChange[];
772
+ targetDirtyFiles: WorktreeChange[];
773
+ verified: boolean;
774
+ reason?: undefined;
775
+ };
776
+ beginWork(params: Parameters<IntentAndTaskEngine['declareIntent']>[0] & {
777
+ isolateWorktree?: boolean;
778
+ }): {
779
+ worktree: SpawnedWorktree | null;
780
+ ok: boolean;
781
+ task: TaskRecord | null;
782
+ fencingToken: number;
783
+ locks: LockRecord[];
784
+ lockConflicts: LockConflict[];
785
+ activeSiblingIntents: TaskRecord[];
786
+ };
787
+ completeWork(params: {
788
+ agentId: string;
789
+ taskId?: string;
790
+ fencingToken?: number;
791
+ mergeBranch?: string;
792
+ verificationCmd?: string;
793
+ }): {
794
+ ok: boolean;
795
+ mergeResult: SpeculativeMergeResult;
796
+ error: string;
797
+ completedTasks?: undefined;
798
+ } | {
799
+ ok: boolean;
800
+ completedTasks: TaskRecord[];
801
+ mergeResult: SpeculativeMergeResult | null;
802
+ error?: undefined;
803
+ };
804
+ close(): void;
805
+ }
806
+
807
+ interface RepositoryLayout {
808
+ checkoutRoot: string;
809
+ commonGitDir: string | null;
810
+ isLinkedWorktree: boolean;
811
+ coordDir: string;
812
+ }
813
+ /** Resolve missing leaves through their nearest existing parent; never hide a broken link. */
814
+ declare function physicalPath(input: string): string;
815
+ declare function isWithin(root: string, target: string): boolean;
816
+ /** Resolve a concrete file, including missing leaves, and refuse symlinks leaving the checkout. */
817
+ declare function repositoryFile(root: string, file: string): string;
818
+ /** Git's common directory identifies shared coordination; Git operations stay in this checkout. */
819
+ declare function discoverRepository(input: string): RepositoryLayout;
820
+ /** Read-only probe using an existing directory; uncertain results retain exclusion. */
821
+ declare function caseSensitivePaths(root: string): boolean;
822
+
823
+ /** Copies a consistent stopped-state set before opening SQLite, so even SHM reconstruction cannot touch original recovery files. */
824
+ declare function readCoordinationState(directory?: string): {
825
+ protocolVersion: string;
826
+ observedAt: number;
827
+ repository: {
828
+ root: string;
829
+ commonGitDir: string | null;
830
+ coordDir: string;
831
+ };
832
+ runtime: {
833
+ node: string;
834
+ };
835
+ state: "ready" | "missing" | "unavailable";
836
+ error: string | undefined;
837
+ fencingEpoch: number;
838
+ agents: AgentRecord[];
839
+ tasks: Record<string, unknown>[];
840
+ locks: Record<string, unknown>[];
841
+ conflicts: Record<string, unknown>[];
842
+ contracts: Record<string, unknown>[];
843
+ resources: Record<string, unknown>[];
844
+ mergeQueue: Record<string, unknown>[];
845
+ quarantined: Record<string, unknown>[];
846
+ mutexWaiters: Record<string, unknown>[];
847
+ commandGuards: Record<string, unknown>[];
848
+ events: Record<string, unknown>[];
849
+ workspaces: ReturnType<typeof observeWorkspaces>;
850
+ } | {
851
+ state: "ready";
852
+ fencingEpoch: number;
853
+ agents: AgentRecord[];
854
+ tasks: {
855
+ depends_on: any;
856
+ scope_globs: any;
857
+ }[];
858
+ locks: Record<string, unknown>[];
859
+ conflicts: {
860
+ details: any;
861
+ }[];
862
+ contracts: {
863
+ is_breaking: boolean;
864
+ }[];
865
+ resources: Record<string, unknown>[];
866
+ mergeQueue: Record<string, unknown>[];
867
+ quarantined: Record<string, unknown>[];
868
+ mutexWaiters: Record<string, unknown>[];
869
+ commandGuards: Record<string, unknown>[];
870
+ events: {
871
+ payload: any;
872
+ }[];
873
+ workspaces: WorkspaceObservation[];
874
+ protocolVersion: string;
875
+ observedAt: number;
876
+ repository: {
877
+ root: string;
878
+ commonGitDir: string | null;
879
+ coordDir: string;
880
+ };
881
+ runtime: {
882
+ node: string;
883
+ };
884
+ error: string | undefined;
885
+ };
886
+ /** Recovery is an inspection report: it never clears guards, expires claims, deletes worktrees or restores files. */
887
+ declare function recoveryReport(directory?: string): {
888
+ retainedWorktrees: {
889
+ path: string;
890
+ symlink: boolean;
891
+ agentIds: string[];
892
+ }[];
893
+ expiredClaims: Record<string, unknown>[];
894
+ unfinishedIntegrations: Record<string, unknown>[];
895
+ setupLock: {
896
+ path: string;
897
+ present: boolean;
898
+ };
899
+ integrationLock: {
900
+ path: string;
901
+ present: boolean;
902
+ };
903
+ protocolVersion: string;
904
+ observedAt: number;
905
+ repository: {
906
+ root: string;
907
+ commonGitDir: string | null;
908
+ coordDir: string;
909
+ };
910
+ runtime: {
911
+ node: string;
912
+ };
913
+ state: "ready" | "missing" | "unavailable";
914
+ error: string | undefined;
915
+ fencingEpoch: number;
916
+ agents: AgentRecord[];
917
+ tasks: Record<string, unknown>[];
918
+ locks: Record<string, unknown>[];
919
+ conflicts: Record<string, unknown>[];
920
+ contracts: Record<string, unknown>[];
921
+ resources: Record<string, unknown>[];
922
+ mergeQueue: Record<string, unknown>[];
923
+ quarantined: Record<string, unknown>[];
924
+ mutexWaiters: Record<string, unknown>[];
925
+ commandGuards: Record<string, unknown>[];
926
+ events: Record<string, unknown>[];
927
+ workspaces: ReturnType<typeof observeWorkspaces>;
928
+ } | {
929
+ retainedWorktrees: {
930
+ path: string;
931
+ symlink: boolean;
932
+ agentIds: string[];
933
+ }[];
934
+ expiredClaims: Record<string, unknown>[];
935
+ unfinishedIntegrations: Record<string, unknown>[];
936
+ setupLock: {
937
+ path: string;
938
+ present: boolean;
939
+ };
940
+ integrationLock: {
941
+ path: string;
942
+ present: boolean;
943
+ };
944
+ state: "ready";
945
+ fencingEpoch: number;
946
+ agents: AgentRecord[];
947
+ tasks: {
948
+ depends_on: any;
949
+ scope_globs: any;
950
+ }[];
951
+ locks: Record<string, unknown>[];
952
+ conflicts: {
953
+ details: any;
954
+ }[];
955
+ contracts: {
956
+ is_breaking: boolean;
957
+ }[];
958
+ resources: Record<string, unknown>[];
959
+ mergeQueue: Record<string, unknown>[];
960
+ quarantined: Record<string, unknown>[];
961
+ mutexWaiters: Record<string, unknown>[];
962
+ commandGuards: Record<string, unknown>[];
963
+ events: {
964
+ payload: any;
965
+ }[];
966
+ workspaces: WorkspaceObservation[];
967
+ protocolVersion: string;
968
+ observedAt: number;
969
+ repository: {
970
+ root: string;
971
+ commonGitDir: string | null;
972
+ coordDir: string;
973
+ };
974
+ runtime: {
975
+ node: string;
976
+ };
977
+ error: string | undefined;
978
+ };
979
+
980
+ declare const KITH_VERSION = "0.1.0";
981
+ declare const KITH_PROTOCOL_VERSION = "1.0.0";
982
+
983
+ export { type AcquireLockResult, type AgentRecord, type AgentUnreadDelta, AstAnalyzer, type BashGuardPostReport, BashMerkleGuard, type BlastRadiusAlert, CoWWorktreeManager, type ConflictRecord, type ContractRecord, CoordDatabase, type CoordEvent, type DeclareIntentResult, DependencyAndContractEngine, type DirtyMergeProbeResult, type ExtractedImport, type ExtractedSymbol, FencingAndAgentManager, type FileAstAnalysis, type FileModificationReport, type FileSnapshotEntry, IntentAndTaskEngine, KITH_PROTOCOL_VERSION, KITH_VERSION, KithEngine, type LockConflict, LockEngine, type LockRecord, type MergeTrainEntry, type PostFileEditHookResult, type QuarantineRecord, type RepositoryLayout, ResourceBroker, type ResourceRecord, SessionOwnershipError, type SessionRegistration, ShadowGitEngine, type SpawnedWorktree, type SpeculativeMergeResult, SpeculativeMergeTrain, StaleFencingTokenError, type SymbolKind, type TaskRecord, type WorkspaceObservation, type WorktreeChange, caseSensitivePaths, discoverRepository, isWithin, observeWorkspaces, physicalPath, previewIntegration, readCoordinationState, recoveryReport, repositoryFile, worktreeChanges };