agents-reverse-engineer 0.1.1

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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +238 -0
  3. package/dist/change-detection/detector.d.ts +24 -0
  4. package/dist/change-detection/detector.d.ts.map +1 -0
  5. package/dist/change-detection/detector.js +114 -0
  6. package/dist/change-detection/detector.js.map +1 -0
  7. package/dist/change-detection/index.d.ts +9 -0
  8. package/dist/change-detection/index.d.ts.map +1 -0
  9. package/dist/change-detection/index.js +8 -0
  10. package/dist/change-detection/index.js.map +1 -0
  11. package/dist/change-detection/types.d.ts +39 -0
  12. package/dist/change-detection/types.d.ts.map +1 -0
  13. package/dist/change-detection/types.js +5 -0
  14. package/dist/change-detection/types.js.map +1 -0
  15. package/dist/cli/discover.d.ts +52 -0
  16. package/dist/cli/discover.d.ts.map +1 -0
  17. package/dist/cli/discover.js +125 -0
  18. package/dist/cli/discover.js.map +1 -0
  19. package/dist/cli/generate.d.ts +41 -0
  20. package/dist/cli/generate.d.ts.map +1 -0
  21. package/dist/cli/generate.js +179 -0
  22. package/dist/cli/generate.js.map +1 -0
  23. package/dist/cli/index.d.ts +12 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +182 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/init.d.ts +38 -0
  28. package/dist/cli/init.d.ts.map +1 -0
  29. package/dist/cli/init.js +94 -0
  30. package/dist/cli/init.js.map +1 -0
  31. package/dist/cli/update.d.ts +28 -0
  32. package/dist/cli/update.d.ts.map +1 -0
  33. package/dist/cli/update.js +296 -0
  34. package/dist/cli/update.js.map +1 -0
  35. package/dist/config/defaults.d.ts +38 -0
  36. package/dist/config/defaults.d.ts.map +1 -0
  37. package/dist/config/defaults.js +89 -0
  38. package/dist/config/defaults.js.map +1 -0
  39. package/dist/config/loader.d.ts +66 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +158 -0
  42. package/dist/config/loader.js.map +1 -0
  43. package/dist/config/schema.d.ts +235 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +80 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/discovery/filters/binary.d.ts +46 -0
  48. package/dist/discovery/filters/binary.d.ts.map +1 -0
  49. package/dist/discovery/filters/binary.js +157 -0
  50. package/dist/discovery/filters/binary.js.map +1 -0
  51. package/dist/discovery/filters/custom.d.ts +26 -0
  52. package/dist/discovery/filters/custom.d.ts.map +1 -0
  53. package/dist/discovery/filters/custom.js +50 -0
  54. package/dist/discovery/filters/custom.js.map +1 -0
  55. package/dist/discovery/filters/gitignore.d.ts +24 -0
  56. package/dist/discovery/filters/gitignore.d.ts.map +1 -0
  57. package/dist/discovery/filters/gitignore.js +53 -0
  58. package/dist/discovery/filters/gitignore.js.map +1 -0
  59. package/dist/discovery/filters/index.d.ts +85 -0
  60. package/dist/discovery/filters/index.d.ts.map +1 -0
  61. package/dist/discovery/filters/index.js +98 -0
  62. package/dist/discovery/filters/index.js.map +1 -0
  63. package/dist/discovery/filters/vendor.d.ts +30 -0
  64. package/dist/discovery/filters/vendor.d.ts.map +1 -0
  65. package/dist/discovery/filters/vendor.js +57 -0
  66. package/dist/discovery/filters/vendor.js.map +1 -0
  67. package/dist/discovery/types.d.ts +66 -0
  68. package/dist/discovery/types.d.ts.map +1 -0
  69. package/dist/discovery/types.js +8 -0
  70. package/dist/discovery/types.js.map +1 -0
  71. package/dist/discovery/walker.d.ts +24 -0
  72. package/dist/discovery/walker.d.ts.map +1 -0
  73. package/dist/discovery/walker.js +35 -0
  74. package/dist/discovery/walker.js.map +1 -0
  75. package/dist/generation/budget/chunker.d.ts +38 -0
  76. package/dist/generation/budget/chunker.d.ts.map +1 -0
  77. package/dist/generation/budget/chunker.js +73 -0
  78. package/dist/generation/budget/chunker.js.map +1 -0
  79. package/dist/generation/budget/counter.d.ts +26 -0
  80. package/dist/generation/budget/counter.d.ts.map +1 -0
  81. package/dist/generation/budget/counter.js +45 -0
  82. package/dist/generation/budget/counter.js.map +1 -0
  83. package/dist/generation/budget/index.d.ts +4 -0
  84. package/dist/generation/budget/index.d.ts.map +1 -0
  85. package/dist/generation/budget/index.js +4 -0
  86. package/dist/generation/budget/index.js.map +1 -0
  87. package/dist/generation/budget/tracker.d.ts +63 -0
  88. package/dist/generation/budget/tracker.d.ts.map +1 -0
  89. package/dist/generation/budget/tracker.js +96 -0
  90. package/dist/generation/budget/tracker.js.map +1 -0
  91. package/dist/generation/complexity.d.ts +43 -0
  92. package/dist/generation/complexity.d.ts.map +1 -0
  93. package/dist/generation/complexity.js +156 -0
  94. package/dist/generation/complexity.js.map +1 -0
  95. package/dist/generation/detection/detector.d.ts +23 -0
  96. package/dist/generation/detection/detector.d.ts.map +1 -0
  97. package/dist/generation/detection/detector.js +62 -0
  98. package/dist/generation/detection/detector.js.map +1 -0
  99. package/dist/generation/detection/patterns.d.ts +21 -0
  100. package/dist/generation/detection/patterns.d.ts.map +1 -0
  101. package/dist/generation/detection/patterns.js +115 -0
  102. package/dist/generation/detection/patterns.js.map +1 -0
  103. package/dist/generation/executor.d.ts +95 -0
  104. package/dist/generation/executor.d.ts.map +1 -0
  105. package/dist/generation/executor.js +352 -0
  106. package/dist/generation/executor.js.map +1 -0
  107. package/dist/generation/orchestrator.d.ts +126 -0
  108. package/dist/generation/orchestrator.d.ts.map +1 -0
  109. package/dist/generation/orchestrator.js +222 -0
  110. package/dist/generation/orchestrator.js.map +1 -0
  111. package/dist/generation/prompts/builder.d.ts +31 -0
  112. package/dist/generation/prompts/builder.d.ts.map +1 -0
  113. package/dist/generation/prompts/builder.js +136 -0
  114. package/dist/generation/prompts/builder.js.map +1 -0
  115. package/dist/generation/prompts/index.d.ts +5 -0
  116. package/dist/generation/prompts/index.d.ts.map +1 -0
  117. package/dist/generation/prompts/index.js +4 -0
  118. package/dist/generation/prompts/index.js.map +1 -0
  119. package/dist/generation/prompts/templates.d.ts +11 -0
  120. package/dist/generation/prompts/templates.d.ts.map +1 -0
  121. package/dist/generation/prompts/templates.js +247 -0
  122. package/dist/generation/prompts/templates.js.map +1 -0
  123. package/dist/generation/prompts/types.d.ts +71 -0
  124. package/dist/generation/prompts/types.d.ts.map +1 -0
  125. package/dist/generation/prompts/types.js +23 -0
  126. package/dist/generation/prompts/types.js.map +1 -0
  127. package/dist/generation/types.d.ts +72 -0
  128. package/dist/generation/types.d.ts.map +1 -0
  129. package/dist/generation/types.js +5 -0
  130. package/dist/generation/types.js.map +1 -0
  131. package/dist/generation/writers/agents-md.d.ts +63 -0
  132. package/dist/generation/writers/agents-md.d.ts.map +1 -0
  133. package/dist/generation/writers/agents-md.js +235 -0
  134. package/dist/generation/writers/agents-md.js.map +1 -0
  135. package/dist/generation/writers/claude-md.d.ts +13 -0
  136. package/dist/generation/writers/claude-md.d.ts.map +1 -0
  137. package/dist/generation/writers/claude-md.js +33 -0
  138. package/dist/generation/writers/claude-md.js.map +1 -0
  139. package/dist/generation/writers/index.d.ts +5 -0
  140. package/dist/generation/writers/index.d.ts.map +1 -0
  141. package/dist/generation/writers/index.js +5 -0
  142. package/dist/generation/writers/index.js.map +1 -0
  143. package/dist/generation/writers/sum.d.ts +37 -0
  144. package/dist/generation/writers/sum.d.ts.map +1 -0
  145. package/dist/generation/writers/sum.js +98 -0
  146. package/dist/generation/writers/sum.js.map +1 -0
  147. package/dist/generation/writers/supplementary.d.ts +53 -0
  148. package/dist/generation/writers/supplementary.d.ts.map +1 -0
  149. package/dist/generation/writers/supplementary.js +195 -0
  150. package/dist/generation/writers/supplementary.js.map +1 -0
  151. package/dist/integration/detect.d.ts +28 -0
  152. package/dist/integration/detect.d.ts.map +1 -0
  153. package/dist/integration/detect.js +64 -0
  154. package/dist/integration/detect.js.map +1 -0
  155. package/dist/integration/generate.d.ts +36 -0
  156. package/dist/integration/generate.d.ts.map +1 -0
  157. package/dist/integration/generate.js +107 -0
  158. package/dist/integration/generate.js.map +1 -0
  159. package/dist/integration/templates.d.ts +42 -0
  160. package/dist/integration/templates.d.ts.map +1 -0
  161. package/dist/integration/templates.js +203 -0
  162. package/dist/integration/templates.js.map +1 -0
  163. package/dist/integration/types.d.ts +44 -0
  164. package/dist/integration/types.d.ts.map +1 -0
  165. package/dist/integration/types.js +8 -0
  166. package/dist/integration/types.js.map +1 -0
  167. package/dist/output/logger.d.ts +86 -0
  168. package/dist/output/logger.d.ts.map +1 -0
  169. package/dist/output/logger.js +107 -0
  170. package/dist/output/logger.js.map +1 -0
  171. package/dist/state/database.d.ts +9 -0
  172. package/dist/state/database.d.ts.map +1 -0
  173. package/dist/state/database.js +66 -0
  174. package/dist/state/database.js.map +1 -0
  175. package/dist/state/index.d.ts +8 -0
  176. package/dist/state/index.d.ts.map +1 -0
  177. package/dist/state/index.js +7 -0
  178. package/dist/state/index.js.map +1 -0
  179. package/dist/state/migrations.d.ts +12 -0
  180. package/dist/state/migrations.d.ts.map +1 -0
  181. package/dist/state/migrations.js +39 -0
  182. package/dist/state/migrations.js.map +1 -0
  183. package/dist/state/types.d.ts +54 -0
  184. package/dist/state/types.d.ts.map +1 -0
  185. package/dist/state/types.js +2 -0
  186. package/dist/state/types.js.map +1 -0
  187. package/dist/types/index.d.ts +39 -0
  188. package/dist/types/index.d.ts.map +1 -0
  189. package/dist/types/index.js +5 -0
  190. package/dist/types/index.js.map +1 -0
  191. package/dist/update/index.d.ts +10 -0
  192. package/dist/update/index.d.ts.map +1 -0
  193. package/dist/update/index.js +9 -0
  194. package/dist/update/index.js.map +1 -0
  195. package/dist/update/orchestrator.d.ts +91 -0
  196. package/dist/update/orchestrator.d.ts.map +1 -0
  197. package/dist/update/orchestrator.js +204 -0
  198. package/dist/update/orchestrator.js.map +1 -0
  199. package/dist/update/orphan-cleaner.d.ts +30 -0
  200. package/dist/update/orphan-cleaner.d.ts.map +1 -0
  201. package/dist/update/orphan-cleaner.js +151 -0
  202. package/dist/update/orphan-cleaner.js.map +1 -0
  203. package/dist/update/types.d.ts +59 -0
  204. package/dist/update/types.d.ts.map +1 -0
  205. package/dist/update/types.js +2 -0
  206. package/dist/update/types.js.map +1 -0
  207. package/package.json +60 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * State types for tracking file generation
3
+ */
4
+ import type Database from 'better-sqlite3';
5
+ /**
6
+ * Record of a file's generation state
7
+ */
8
+ export interface FileRecord {
9
+ /** Relative path from project root */
10
+ path: string;
11
+ /** SHA-256 hash of file content */
12
+ content_hash: string;
13
+ /** ISO timestamp when .sum was generated (null if not yet generated) */
14
+ sum_generated_at: string | null;
15
+ /** Commit hash when file was last analyzed */
16
+ last_analyzed_commit: string | null;
17
+ }
18
+ /**
19
+ * Record of a generation/update run
20
+ */
21
+ export interface RunRecord {
22
+ /** Auto-incremented ID */
23
+ id: number;
24
+ /** Git commit hash at run time */
25
+ commit_hash: string;
26
+ /** ISO timestamp when run completed */
27
+ completed_at: string;
28
+ /** Number of files analyzed in this run */
29
+ files_analyzed: number;
30
+ /** Number of files skipped (unchanged) */
31
+ files_skipped: number;
32
+ }
33
+ /**
34
+ * Interface for state database operations
35
+ */
36
+ export interface StateDatabase {
37
+ /** Get file record by path */
38
+ getFile(path: string): FileRecord | undefined;
39
+ /** Insert or update file record */
40
+ upsertFile(record: FileRecord): void;
41
+ /** Delete file record */
42
+ deleteFile(path: string): void;
43
+ /** Get all file records */
44
+ getAllFiles(): FileRecord[];
45
+ /** Get the most recent run record */
46
+ getLastRun(): RunRecord | undefined;
47
+ /** Insert a new run record */
48
+ insertRun(run: Omit<RunRecord, 'id'>): number;
49
+ /** Close the database connection */
50
+ close(): void;
51
+ /** Get the underlying database for transactions */
52
+ getDb(): Database.Database;
53
+ }
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,8CAA8C;IAC9C,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,0BAA0B;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC9C,mCAAmC;IACnC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACrC,yBAAyB;IACzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2BAA2B;IAC3B,WAAW,IAAI,UAAU,EAAE,CAAC;IAC5B,qCAAqC;IACrC,UAAU,IAAI,SAAS,GAAG,SAAS,CAAC;IACpC,8BAA8B;IAC9B,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC;IAC9C,oCAAoC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,mDAAmD;IACnD,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/state/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared types used across modules
3
+ */
4
+ /**
5
+ * Log level for controlling output verbosity
6
+ */
7
+ export type LogLevel = 'verbose' | 'normal' | 'quiet';
8
+ /**
9
+ * Information about an excluded file
10
+ */
11
+ export interface ExcludedFile {
12
+ /** Absolute or relative path to the excluded file */
13
+ path: string;
14
+ /** Reason for exclusion (e.g., "gitignore pattern", "binary file", "vendor directory") */
15
+ reason: string;
16
+ }
17
+ /**
18
+ * Result of the file discovery process
19
+ */
20
+ export interface DiscoveryResult {
21
+ /** List of file paths that should be analyzed */
22
+ files: string[];
23
+ /** List of files that were excluded with reasons */
24
+ excluded: ExcludedFile[];
25
+ }
26
+ /**
27
+ * Statistics about the discovery process
28
+ */
29
+ export interface DiscoveryStats {
30
+ /** Total number of files found */
31
+ totalFiles: number;
32
+ /** Number of files included for analysis */
33
+ includedFiles: number;
34
+ /** Number of files excluded */
35
+ excludedFiles: number;
36
+ /** Breakdown of exclusion reasons */
37
+ exclusionReasons: Record<string, number>;
38
+ }
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types used across modules
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Update module
3
+ *
4
+ * Provides incremental documentation update functionality.
5
+ * Coordinates state management, change detection, and orphan cleanup.
6
+ */
7
+ export { UpdateOrchestrator, createUpdateOrchestrator, type UpdatePlan, } from './orchestrator.js';
8
+ export { cleanupOrphans, cleanupEmptyDirectoryDocs, getAffectedDirectories, } from './orphan-cleaner.js';
9
+ export type { UpdateOptions, UpdateResult, UpdateProgress, CleanupResult, } from './types.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/update/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Update module
3
+ *
4
+ * Provides incremental documentation update functionality.
5
+ * Coordinates state management, change detection, and orphan cleanup.
6
+ */
7
+ export { UpdateOrchestrator, createUpdateOrchestrator, } from './orchestrator.js';
8
+ export { cleanupOrphans, cleanupEmptyDirectoryDocs, getAffectedDirectories, } from './orphan-cleaner.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/update/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GAEzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,91 @@
1
+ import type { Config } from '../config/schema.js';
2
+ import type { StateDatabase, RunRecord } from '../state/index.js';
3
+ import { type FileChange } from '../change-detection/index.js';
4
+ import type { UpdateOptions, CleanupResult } from './types.js';
5
+ /**
6
+ * Result of update preparation (before analysis).
7
+ */
8
+ export interface UpdatePlan {
9
+ /** Files to analyze (added or modified) */
10
+ filesToAnalyze: FileChange[];
11
+ /** Files to skip (unchanged based on content hash) */
12
+ filesToSkip: string[];
13
+ /** Cleanup result (files to delete) */
14
+ cleanup: CleanupResult;
15
+ /** Directories that need AGENTS.md regeneration */
16
+ affectedDirs: string[];
17
+ /** Base commit (from last run or initial) */
18
+ baseCommit: string;
19
+ /** Current commit */
20
+ currentCommit: string;
21
+ /** Whether this is first run (no prior state) */
22
+ isFirstRun: boolean;
23
+ }
24
+ /**
25
+ * Orchestrates incremental documentation updates.
26
+ */
27
+ export declare class UpdateOrchestrator {
28
+ private config;
29
+ private projectRoot;
30
+ private db;
31
+ constructor(config: Config, projectRoot: string);
32
+ /**
33
+ * Get path to state database.
34
+ */
35
+ private getDbPath;
36
+ /**
37
+ * Ensure state directory exists and open database.
38
+ */
39
+ openState(): Promise<StateDatabase>;
40
+ /**
41
+ * Close database connection.
42
+ */
43
+ close(): void;
44
+ /**
45
+ * Check prerequisites for update.
46
+ *
47
+ * @throws Error if not in a git repository
48
+ */
49
+ checkPrerequisites(): Promise<void>;
50
+ /**
51
+ * Prepare update plan without executing analysis.
52
+ *
53
+ * @param options - Update options
54
+ * @returns Update plan with files to analyze and cleanup actions
55
+ */
56
+ preparePlan(options?: UpdateOptions): Promise<UpdatePlan>;
57
+ /**
58
+ * Update state for a successfully analyzed file.
59
+ *
60
+ * @param relativePath - Relative path to the file
61
+ * @param contentHash - SHA-256 hash of file content
62
+ * @param currentCommit - Current git commit hash
63
+ */
64
+ recordFileAnalyzed(relativePath: string, contentHash: string, currentCommit: string): Promise<void>;
65
+ /**
66
+ * Remove file from state (for deleted files).
67
+ */
68
+ removeFileState(relativePath: string): Promise<void>;
69
+ /**
70
+ * Record a completed update run.
71
+ *
72
+ * @param commitHash - Git commit hash at completion
73
+ * @param filesAnalyzed - Number of files analyzed
74
+ * @param filesSkipped - Number of files skipped
75
+ * @returns Run ID
76
+ */
77
+ recordRun(commitHash: string, filesAnalyzed: number, filesSkipped: number): Promise<number>;
78
+ /**
79
+ * Get last run information.
80
+ */
81
+ getLastRun(): Promise<RunRecord | undefined>;
82
+ /**
83
+ * Check if this is the first run (no prior state).
84
+ */
85
+ isFirstRun(): Promise<boolean>;
86
+ }
87
+ /**
88
+ * Create an update orchestrator.
89
+ */
90
+ export declare function createUpdateOrchestrator(config: Config, projectRoot: string): UpdateOrchestrator;
91
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/update/orchestrator.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAc,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9E,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACd,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,cAAc,EAAE,UAAU,EAAE,CAAC;IAC7B,sDAAsD;IACtD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uCAAuC;IACvC,OAAO,EAAE,aAAa,CAAC;IACvB,mDAAmD;IACnD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,EAAE,CAA8B;gBAE5B,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAK/C;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;IAWzC;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;;;OAIG;IACG,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUzC;;;;;OAKG;IACG,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;IAuFnE;;;;;;OAMG;IACG,kBAAkB,CACtB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1D;;;;;;;OAOG;IACG,SAAS,CACb,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC;IAUlB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAKlD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;CAIrC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,kBAAkB,CAEpB"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Update orchestrator
3
+ *
4
+ * Coordinates incremental documentation updates:
5
+ * 1. Check git repository status
6
+ * 2. Get last run from state database
7
+ * 3. Detect changed files since last run
8
+ * 4. Clean up orphaned .sum files
9
+ * 5. Prepare analysis tasks for changed files
10
+ * 6. Track affected directories for AGENTS.md regeneration
11
+ * 7. Persist new state after successful completion
12
+ */
13
+ import * as path from 'node:path';
14
+ import { mkdir } from 'node:fs/promises';
15
+ import { openDatabase } from '../state/index.js';
16
+ import { isGitRepo, getCurrentCommit, getChangedFiles, computeContentHash, } from '../change-detection/index.js';
17
+ import { cleanupOrphans, getAffectedDirectories } from './orphan-cleaner.js';
18
+ /** State directory name (relative to project root) */
19
+ const STATE_DIR = '.agents-reverse-engineer';
20
+ /** State database filename */
21
+ const STATE_DB = 'state.db';
22
+ /**
23
+ * Orchestrates incremental documentation updates.
24
+ */
25
+ export class UpdateOrchestrator {
26
+ config;
27
+ projectRoot;
28
+ db = null;
29
+ constructor(config, projectRoot) {
30
+ this.config = config;
31
+ this.projectRoot = projectRoot;
32
+ }
33
+ /**
34
+ * Get path to state database.
35
+ */
36
+ getDbPath() {
37
+ return path.join(this.projectRoot, STATE_DIR, STATE_DB);
38
+ }
39
+ /**
40
+ * Ensure state directory exists and open database.
41
+ */
42
+ async openState() {
43
+ if (this.db)
44
+ return this.db;
45
+ // Ensure state directory exists
46
+ const stateDir = path.join(this.projectRoot, STATE_DIR);
47
+ await mkdir(stateDir, { recursive: true });
48
+ this.db = openDatabase(this.getDbPath());
49
+ return this.db;
50
+ }
51
+ /**
52
+ * Close database connection.
53
+ */
54
+ close() {
55
+ if (this.db) {
56
+ this.db.close();
57
+ this.db = null;
58
+ }
59
+ }
60
+ /**
61
+ * Check prerequisites for update.
62
+ *
63
+ * @throws Error if not in a git repository
64
+ */
65
+ async checkPrerequisites() {
66
+ const isRepo = await isGitRepo(this.projectRoot);
67
+ if (!isRepo) {
68
+ throw new Error(`Not a git repository: ${this.projectRoot}\n` +
69
+ 'The update command requires a git repository for change detection.');
70
+ }
71
+ }
72
+ /**
73
+ * Prepare update plan without executing analysis.
74
+ *
75
+ * @param options - Update options
76
+ * @returns Update plan with files to analyze and cleanup actions
77
+ */
78
+ async preparePlan(options = {}) {
79
+ await this.checkPrerequisites();
80
+ const db = await this.openState();
81
+ // Get current commit
82
+ const currentCommit = await getCurrentCommit(this.projectRoot);
83
+ // Get last run to determine base commit
84
+ const lastRun = db.getLastRun();
85
+ const isFirstRun = !lastRun;
86
+ const baseCommit = lastRun?.commit_hash ?? currentCommit;
87
+ // If first run or same commit, no committed changes
88
+ let changes = [];
89
+ if (!isFirstRun && baseCommit !== currentCommit) {
90
+ const result = await getChangedFiles(this.projectRoot, baseCommit, { includeUncommitted: options.includeUncommitted });
91
+ changes = result.changes;
92
+ }
93
+ else if (options.includeUncommitted) {
94
+ // Even if no committed changes, check uncommitted
95
+ const result = await getChangedFiles(this.projectRoot, currentCommit, // Use current as base (no committed diff)
96
+ { includeUncommitted: true });
97
+ changes = result.changes;
98
+ }
99
+ // Separate files by status for different handling
100
+ const filesToAnalyze = changes.filter(c => c.status === 'added' || c.status === 'modified' || c.status === 'renamed');
101
+ const deletedOrRenamed = changes.filter(c => c.status === 'deleted' || c.status === 'renamed');
102
+ // Filter out files that haven't actually changed (content hash match)
103
+ const actuallyChanged = [];
104
+ const filesToSkip = [];
105
+ for (const change of filesToAnalyze) {
106
+ if (change.status === 'added') {
107
+ // New files are always analyzed
108
+ actuallyChanged.push(change);
109
+ }
110
+ else {
111
+ // For modified/renamed, check content hash
112
+ const filePath = path.join(this.projectRoot, change.path);
113
+ try {
114
+ const currentHash = await computeContentHash(filePath);
115
+ const stored = db.getFile(change.path);
116
+ if (!stored || stored.content_hash !== currentHash) {
117
+ actuallyChanged.push(change);
118
+ }
119
+ else {
120
+ filesToSkip.push(change.path);
121
+ }
122
+ }
123
+ catch {
124
+ // File can't be read - skip it
125
+ filesToSkip.push(change.path);
126
+ }
127
+ }
128
+ }
129
+ // Cleanup orphans (deleted and renamed old paths)
130
+ const cleanup = await cleanupOrphans(this.projectRoot, deletedOrRenamed, options.dryRun ?? false);
131
+ // Get directories affected by changes (for AGENTS.md regeneration)
132
+ const affectedDirs = Array.from(getAffectedDirectories(actuallyChanged));
133
+ return {
134
+ filesToAnalyze: actuallyChanged,
135
+ filesToSkip,
136
+ cleanup,
137
+ affectedDirs,
138
+ baseCommit,
139
+ currentCommit,
140
+ isFirstRun,
141
+ };
142
+ }
143
+ /**
144
+ * Update state for a successfully analyzed file.
145
+ *
146
+ * @param relativePath - Relative path to the file
147
+ * @param contentHash - SHA-256 hash of file content
148
+ * @param currentCommit - Current git commit hash
149
+ */
150
+ async recordFileAnalyzed(relativePath, contentHash, currentCommit) {
151
+ const db = await this.openState();
152
+ db.upsertFile({
153
+ path: relativePath,
154
+ content_hash: contentHash,
155
+ sum_generated_at: new Date().toISOString(),
156
+ last_analyzed_commit: currentCommit,
157
+ });
158
+ }
159
+ /**
160
+ * Remove file from state (for deleted files).
161
+ */
162
+ async removeFileState(relativePath) {
163
+ const db = await this.openState();
164
+ db.deleteFile(relativePath);
165
+ }
166
+ /**
167
+ * Record a completed update run.
168
+ *
169
+ * @param commitHash - Git commit hash at completion
170
+ * @param filesAnalyzed - Number of files analyzed
171
+ * @param filesSkipped - Number of files skipped
172
+ * @returns Run ID
173
+ */
174
+ async recordRun(commitHash, filesAnalyzed, filesSkipped) {
175
+ const db = await this.openState();
176
+ return db.insertRun({
177
+ commit_hash: commitHash,
178
+ completed_at: new Date().toISOString(),
179
+ files_analyzed: filesAnalyzed,
180
+ files_skipped: filesSkipped,
181
+ });
182
+ }
183
+ /**
184
+ * Get last run information.
185
+ */
186
+ async getLastRun() {
187
+ const db = await this.openState();
188
+ return db.getLastRun();
189
+ }
190
+ /**
191
+ * Check if this is the first run (no prior state).
192
+ */
193
+ async isFirstRun() {
194
+ const db = await this.openState();
195
+ return !db.getLastRun();
196
+ }
197
+ }
198
+ /**
199
+ * Create an update orchestrator.
200
+ */
201
+ export function createUpdateOrchestrator(config, projectRoot) {
202
+ return new UpdateOrchestrator(config, projectRoot);
203
+ }
204
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/update/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { FileChange } from '../change-detection/types.js';
2
+ import type { CleanupResult } from './types.js';
3
+ /**
4
+ * Clean up orphaned .sum files and empty AGENTS.md files.
5
+ *
6
+ * @param projectRoot - Absolute path to project root
7
+ * @param changes - List of file changes (deleted and renamed files need cleanup)
8
+ * @param dryRun - If true, don't actually delete files
9
+ * @returns Cleanup result with lists of deleted files
10
+ */
11
+ export declare function cleanupOrphans(projectRoot: string, changes: FileChange[], dryRun?: boolean): Promise<CleanupResult>;
12
+ /**
13
+ * Check if a directory has any source files remaining.
14
+ * If not, delete its AGENTS.md.
15
+ *
16
+ * @param dirPath - Absolute path to directory
17
+ * @param dryRun - If true, don't actually delete
18
+ * @returns true if AGENTS.md was deleted
19
+ */
20
+ export declare function cleanupEmptyDirectoryDocs(dirPath: string, dryRun?: boolean): Promise<boolean>;
21
+ /**
22
+ * Get list of directories that should have their AGENTS.md regenerated.
23
+ *
24
+ * Includes parent directories of changed files up to project root.
25
+ *
26
+ * @param changes - List of file changes (non-deleted files)
27
+ * @returns Set of relative directory paths
28
+ */
29
+ export declare function getAffectedDirectories(changes: FileChange[]): Set<string>;
30
+ //# sourceMappingURL=orphan-cleaner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-cleaner.d.ts","sourceRoot":"","sources":["../../src/update/orphan-cleaner.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAahD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,aAAa,CAAC,CA8CxB;AAoBD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,OAAO,CAAC,CA2BlB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAkBzE"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Orphan cleanup for stale .sum and AGENTS.md files
3
+ *
4
+ * Handles:
5
+ * - Deleting .sum files when source files are deleted
6
+ * - Deleting .sum files for renamed files (at old path)
7
+ * - Deleting AGENTS.md from directories with no remaining source files
8
+ */
9
+ import { unlink, readdir, stat } from 'node:fs/promises';
10
+ import * as path from 'node:path';
11
+ /**
12
+ * Files to ignore when checking if a directory has source files.
13
+ * These are generated files, not source files.
14
+ */
15
+ const GENERATED_FILES = new Set([
16
+ 'AGENTS.md',
17
+ 'CLAUDE.md',
18
+ 'ARCHITECTURE.md',
19
+ 'STACK.md',
20
+ ]);
21
+ /**
22
+ * Clean up orphaned .sum files and empty AGENTS.md files.
23
+ *
24
+ * @param projectRoot - Absolute path to project root
25
+ * @param changes - List of file changes (deleted and renamed files need cleanup)
26
+ * @param dryRun - If true, don't actually delete files
27
+ * @returns Cleanup result with lists of deleted files
28
+ */
29
+ export async function cleanupOrphans(projectRoot, changes, dryRun = false) {
30
+ const result = {
31
+ deletedSumFiles: [],
32
+ deletedAgentsMd: [],
33
+ };
34
+ // Collect paths that need .sum cleanup
35
+ const pathsToClean = [];
36
+ for (const change of changes) {
37
+ if (change.status === 'deleted') {
38
+ pathsToClean.push(change.path);
39
+ }
40
+ else if (change.status === 'renamed' && change.oldPath) {
41
+ // For renames, clean up the old path's .sum
42
+ pathsToClean.push(change.oldPath);
43
+ }
44
+ }
45
+ // Delete .sum files for deleted/renamed source files
46
+ for (const relativePath of pathsToClean) {
47
+ const sumPath = path.join(projectRoot, `${relativePath}.sum`);
48
+ const deleted = await deleteIfExists(sumPath, dryRun);
49
+ if (deleted) {
50
+ result.deletedSumFiles.push(relativePath + '.sum');
51
+ }
52
+ }
53
+ // Collect affected directories for AGENTS.md cleanup
54
+ const affectedDirs = new Set();
55
+ for (const relativePath of pathsToClean) {
56
+ const dir = path.dirname(relativePath);
57
+ if (dir && dir !== '.') {
58
+ affectedDirs.add(dir);
59
+ }
60
+ }
61
+ // Check each affected directory for empty AGENTS.md
62
+ for (const dir of affectedDirs) {
63
+ const dirPath = path.join(projectRoot, dir);
64
+ const cleaned = await cleanupEmptyDirectoryDocs(dirPath, dryRun);
65
+ if (cleaned) {
66
+ result.deletedAgentsMd.push(path.join(dir, 'AGENTS.md'));
67
+ }
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Delete a file if it exists.
73
+ *
74
+ * @returns true if file was deleted (or would be in dry run)
75
+ */
76
+ async function deleteIfExists(filePath, dryRun) {
77
+ try {
78
+ await stat(filePath);
79
+ if (!dryRun) {
80
+ await unlink(filePath);
81
+ }
82
+ return true;
83
+ }
84
+ catch {
85
+ // File doesn't exist
86
+ return false;
87
+ }
88
+ }
89
+ /**
90
+ * Check if a directory has any source files remaining.
91
+ * If not, delete its AGENTS.md.
92
+ *
93
+ * @param dirPath - Absolute path to directory
94
+ * @param dryRun - If true, don't actually delete
95
+ * @returns true if AGENTS.md was deleted
96
+ */
97
+ export async function cleanupEmptyDirectoryDocs(dirPath, dryRun = false) {
98
+ try {
99
+ const entries = await readdir(dirPath);
100
+ // Check if directory has any source files
101
+ // Source files are: not .sum files, not generated docs, not hidden files
102
+ const hasSourceFiles = entries.some(entry => {
103
+ // Skip hidden files
104
+ if (entry.startsWith('.'))
105
+ return false;
106
+ // Skip .sum files
107
+ if (entry.endsWith('.sum'))
108
+ return false;
109
+ // Skip known generated files
110
+ if (GENERATED_FILES.has(entry))
111
+ return false;
112
+ // Everything else counts as a source file
113
+ return true;
114
+ });
115
+ if (!hasSourceFiles) {
116
+ const agentsPath = path.join(dirPath, 'AGENTS.md');
117
+ return await deleteIfExists(agentsPath, dryRun);
118
+ }
119
+ return false;
120
+ }
121
+ catch {
122
+ // Directory doesn't exist or can't be read
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ * Get list of directories that should have their AGENTS.md regenerated.
128
+ *
129
+ * Includes parent directories of changed files up to project root.
130
+ *
131
+ * @param changes - List of file changes (non-deleted files)
132
+ * @returns Set of relative directory paths
133
+ */
134
+ export function getAffectedDirectories(changes) {
135
+ const dirs = new Set();
136
+ for (const change of changes) {
137
+ // Skip deleted files - they don't affect directory docs
138
+ if (change.status === 'deleted')
139
+ continue;
140
+ // Add all parent directories up to root
141
+ let dir = path.dirname(change.path);
142
+ while (dir && dir !== '.') {
143
+ dirs.add(dir);
144
+ dir = path.dirname(dir);
145
+ }
146
+ // Include root directory
147
+ dirs.add('.');
148
+ }
149
+ return dirs;
150
+ }
151
+ //# sourceMappingURL=orphan-cleaner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-cleaner.js","sourceRoot":"","sources":["../../src/update/orphan-cleaner.ts"],"names":[],"mappings":"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"}