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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GeoloeG-IsT
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ <div align="center">
2
+
3
+ # AGENTS REVERSE ENGINEER
4
+
5
+ **Reverse engineer your codebase into AI-friendly documentation.**
6
+
7
+ **Generate `.sum` files, `AGENTS.md`, and root docs for Claude Code, OpenCode, and any AI assistant that supports `AGENTS.md`.**
8
+
9
+ [![npm version](https://img.shields.io/npm/v/agents-reverse-engineer?style=for-the-badge&logo=npm&logoColor=white&color=CB3837)](https://www.npmjs.com/package/agents-reverse-engineer)
10
+ [![License](https://img.shields.io/badge/license-MIT-blue?style=for-the-badge)](LICENSE)
11
+
12
+ <br>
13
+
14
+ ```bash
15
+ npx agents-reverse-engineer init --integration
16
+ ```
17
+
18
+ **Works on Mac, Windows, and Linux.**
19
+
20
+ <br>
21
+
22
+ _"Finally, my AI assistant actually understands my codebase structure."_
23
+
24
+ _"No more explaining the same architecture in every conversation."_
25
+
26
+ <br>
27
+
28
+ [Why This Exists](#why-this-exists) · [How It Works](#how-it-works) · [Commands](#commands) · [Generated Docs](#generated-documentation)
29
+
30
+ </div>
31
+
32
+ ---
33
+
34
+ ## Why This Exists
35
+
36
+ AI coding assistants are powerful, but they don't know your codebase. Every session starts fresh. You explain the same architecture, the same patterns, the same file locations — over and over.
37
+
38
+ **agents-reverse-engineer** fixes that. It generates documentation that AI assistants actually read:
39
+
40
+ - **`.sum` files** — Per-file summaries with purpose, exports, dependencies
41
+ - **`AGENTS.md`** — Per-directory overviews with file organization (standard format)
42
+ - **`CLAUDE.md`** — Project entry point for Claude Code
43
+ - **`CODEX.md`** — Project entry point for OpenCode *(coming soon)*
44
+
45
+ The result: Your AI assistant understands your codebase from the first message.
46
+
47
+ ---
48
+
49
+ ## Who This Is For
50
+
51
+ Developers using AI coding assistants (Claude Code, OpenCode, Gemini CLI, or any tool supporting `AGENTS.md`) who want their assistant to actually understand their project structure — without manually writing documentation or repeating context every session.
52
+
53
+ ---
54
+
55
+ ## Getting Started
56
+
57
+ ```bash
58
+ npx agents-reverse-engineer init --integration
59
+ ```
60
+
61
+ This creates:
62
+
63
+ 1. **Config** — `.agents-reverse-engineer/config.yaml`
64
+ 2. **Commands** — `.claude/commands/are/` for Claude Code (other runtimes coming soon)
65
+
66
+ Then discover your files and create the plan:
67
+
68
+ ```bash
69
+ npx are discover --plan
70
+ ```
71
+
72
+ Finally, in your AI assistant:
73
+
74
+ ```
75
+ /are:generate
76
+ ```
77
+
78
+ The assistant reads the plan and generates all documentation.
79
+
80
+ > **Note:** The generated `AGENTS.md` files work with any AI assistant that supports this format. The `/are:*` commands currently target Claude Code, with OpenCode and Gemini CLI support planned.
81
+
82
+ ### Staying Updated
83
+
84
+ ```bash
85
+ npx agents-reverse-engineer@latest init --integration
86
+ ```
87
+
88
+ ---
89
+
90
+ ## How It Works
91
+
92
+ ### 1. Initialize
93
+
94
+ ```bash
95
+ are init --integration
96
+ ```
97
+
98
+ Creates configuration and Claude Code commands in your project.
99
+
100
+ ---
101
+
102
+ ### 2. Discover & Plan
103
+
104
+ ```bash
105
+ are discover --plan
106
+ ```
107
+
108
+ Scans your codebase (respecting `.gitignore`), detects file types, and creates `GENERATION-PLAN.md` with all files to analyze.
109
+
110
+ Uses **post-order traversal** — deepest directories first, so child documentation exists before parent directories are documented.
111
+
112
+ ---
113
+
114
+ ### 3. Generate (in your AI assistant)
115
+
116
+ ```
117
+ /are:generate
118
+ ```
119
+
120
+ Your AI assistant executes the plan:
121
+
122
+ 1. **File Analysis** — Creates `.sum` file for each source file
123
+ 2. **Directory Docs** — Creates `AGENTS.md` for each directory
124
+ 3. **Root Docs** — Creates `CLAUDE.md`, `ARCHITECTURE.md`, `STACK.md`
125
+
126
+ ---
127
+
128
+ ### 4. Update Incrementally
129
+
130
+ ```
131
+ /are:update
132
+ ```
133
+
134
+ Only regenerates documentation for files that changed since last run.
135
+
136
+ ---
137
+
138
+ ## Commands
139
+
140
+ | Command | Description |
141
+ | ------------------------------ | -------------------------------- |
142
+ | `are init` | Create configuration file |
143
+ | `are init --integration` | Also create Claude Code commands |
144
+ | `are discover` | List files that will be analyzed |
145
+ | `are discover --plan` | Create GENERATION-PLAN.md |
146
+ | `are discover --show-excluded` | Show excluded files with reasons |
147
+
148
+ ### AI Assistant Commands
149
+
150
+ | Command | Description | Supported Runtimes |
151
+ | --------------- | ------------------------------ | ------------------ |
152
+ | `/are:init` | Initialize config and commands | Claude Code |
153
+ | `/are:generate` | Generate all documentation | Claude Code |
154
+ | `/are:update` | Update changed files only | Claude Code |
155
+ | `/are:discover` | Rediscover and regenerate plan | Claude Code |
156
+ | `/are:clean` | Remove all generated docs | Claude Code |
157
+
158
+ > OpenCode and Gemini CLI command support coming soon.
159
+
160
+ ---
161
+
162
+ ## Generated Documentation
163
+
164
+ ### `.sum` Files (Per File)
165
+
166
+ ```yaml
167
+ ---
168
+ file_type: service
169
+ generated_at: 2026-01-30T12:00:00Z
170
+ ---
171
+
172
+ ## Purpose
173
+ Handles user authentication via JWT tokens.
174
+
175
+ ## Public Interface
176
+ - `authenticate(token: string): User`
177
+ - `generateToken(user: User): string`
178
+
179
+ ## Dependencies
180
+ - jsonwebtoken: Token signing/verification
181
+ - ./user-repository: User data access
182
+
183
+ ## Implementation Notes
184
+ Tokens expire after 24 hours. Refresh handled by client.
185
+ ```
186
+
187
+ ### `AGENTS.md` (Per Directory)
188
+
189
+ Directory overview with:
190
+
191
+ - Description of the directory's role
192
+ - Files grouped by purpose (Types, Services, Utils, etc.)
193
+ - Subdirectories with brief descriptions
194
+
195
+ ### Root Documents
196
+
197
+ - **`CLAUDE.md`** — Project entry point for Claude Code (auto-loaded)
198
+ - **`AGENTS.md`** — Root directory overview (universal format)
199
+ - **`ARCHITECTURE.md`** — System design overview (generated for complex projects)
200
+ - **`STACK.md`** — Technology stack from package.json
201
+
202
+ ---
203
+
204
+ ## Configuration
205
+
206
+ Edit `.agents-reverse-engineer/config.yaml`:
207
+
208
+ ```yaml
209
+ exclude:
210
+ patterns: [] # Custom glob patterns
211
+ vendorDirs: # Directories to skip
212
+ - node_modules
213
+ - dist
214
+ - .git
215
+ binaryExtensions: # File types to skip
216
+ - .png
217
+ - .jpg
218
+
219
+ options:
220
+ followSymlinks: false
221
+ maxFileSize: 1048576 # 1MB
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Requirements
227
+
228
+ - **Node.js 18+**
229
+ - **AI Coding Assistant** — One of:
230
+ - [Claude Code](https://claude.ai/claude-code) (full support)
231
+ - [OpenCode](https://github.com/opencode-ai/opencode) (AGENTS.md supported)
232
+ - Any assistant supporting `AGENTS.md` format
233
+
234
+ ---
235
+
236
+ ## License
237
+
238
+ MIT
@@ -0,0 +1,24 @@
1
+ import type { ChangeDetectionResult, ChangeDetectionOptions } from './types.js';
2
+ /**
3
+ * Check if a path is inside a git repository.
4
+ */
5
+ export declare function isGitRepo(projectRoot: string): Promise<boolean>;
6
+ /**
7
+ * Get the current HEAD commit hash.
8
+ */
9
+ export declare function getCurrentCommit(projectRoot: string): Promise<string>;
10
+ /**
11
+ * Detect files changed since a base commit.
12
+ *
13
+ * Uses git diff with --name-status and -M for rename detection.
14
+ * Optionally includes uncommitted changes (staged + working directory).
15
+ */
16
+ export declare function getChangedFiles(projectRoot: string, baseCommit: string, options?: ChangeDetectionOptions): Promise<ChangeDetectionResult>;
17
+ /**
18
+ * Compute SHA-256 hash of a file's content.
19
+ *
20
+ * @param filePath - Absolute path to the file
21
+ * @returns Hex-encoded SHA-256 hash
22
+ */
23
+ export declare function computeContentHash(filePath: string): Promise<string>;
24
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/change-detection/detector.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAc,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE5F;;GAEG;AACH,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGrE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI3E;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAgFhC;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG1E"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Git change detection and content hashing
3
+ *
4
+ * Uses simple-git for git operations and Node.js crypto for hashing.
5
+ */
6
+ import { simpleGit } from 'simple-git';
7
+ import { createHash } from 'node:crypto';
8
+ import { readFile } from 'node:fs/promises';
9
+ /**
10
+ * Check if a path is inside a git repository.
11
+ */
12
+ export async function isGitRepo(projectRoot) {
13
+ const git = simpleGit(projectRoot);
14
+ return git.checkIsRepo();
15
+ }
16
+ /**
17
+ * Get the current HEAD commit hash.
18
+ */
19
+ export async function getCurrentCommit(projectRoot) {
20
+ const git = simpleGit(projectRoot);
21
+ const hash = await git.revparse(['HEAD']);
22
+ return hash.trim();
23
+ }
24
+ /**
25
+ * Detect files changed since a base commit.
26
+ *
27
+ * Uses git diff with --name-status and -M for rename detection.
28
+ * Optionally includes uncommitted changes (staged + working directory).
29
+ */
30
+ export async function getChangedFiles(projectRoot, baseCommit, options = {}) {
31
+ const git = simpleGit(projectRoot);
32
+ const currentCommit = await getCurrentCommit(projectRoot);
33
+ const changes = [];
34
+ // Get committed changes from baseCommit to HEAD
35
+ const diff = await git.diff([
36
+ '--name-status',
37
+ '-M', // Detect renames (50% similarity threshold)
38
+ baseCommit,
39
+ 'HEAD',
40
+ ]);
41
+ // Parse diff output
42
+ // Format: STATUS\tFILE (or STATUS\tOLD\tNEW for renames)
43
+ const lines = diff.trim().split('\n').filter(line => line.length > 0);
44
+ for (const line of lines) {
45
+ const parts = line.split('\t');
46
+ if (parts.length < 2)
47
+ continue;
48
+ const status = parts[0];
49
+ const filePath = parts[parts.length - 1]; // Last part is always the (new) path
50
+ if (status === 'A') {
51
+ changes.push({ path: filePath, status: 'added' });
52
+ }
53
+ else if (status === 'M') {
54
+ changes.push({ path: filePath, status: 'modified' });
55
+ }
56
+ else if (status === 'D') {
57
+ changes.push({ path: filePath, status: 'deleted' });
58
+ }
59
+ else if (status.startsWith('R')) {
60
+ // Rename: R100 old new (R followed by similarity percentage)
61
+ const oldPath = parts[1];
62
+ changes.push({
63
+ path: filePath,
64
+ status: 'renamed',
65
+ oldPath,
66
+ });
67
+ }
68
+ }
69
+ // Optionally include uncommitted changes
70
+ if (options.includeUncommitted) {
71
+ const status = await git.status();
72
+ // Modified but not staged
73
+ for (const file of status.modified) {
74
+ if (!changes.some(c => c.path === file)) {
75
+ changes.push({ path: file, status: 'modified' });
76
+ }
77
+ }
78
+ // Staged for deletion
79
+ for (const file of status.deleted) {
80
+ if (!changes.some(c => c.path === file)) {
81
+ changes.push({ path: file, status: 'deleted' });
82
+ }
83
+ }
84
+ // Untracked files (new files not yet added)
85
+ for (const file of status.not_added) {
86
+ if (!changes.some(c => c.path === file)) {
87
+ changes.push({ path: file, status: 'added' });
88
+ }
89
+ }
90
+ // Staged files (new or modified)
91
+ for (const file of status.staged) {
92
+ if (!changes.some(c => c.path === file)) {
93
+ changes.push({ path: file, status: 'added' });
94
+ }
95
+ }
96
+ }
97
+ return {
98
+ currentCommit,
99
+ baseCommit,
100
+ changes,
101
+ includesUncommitted: options.includeUncommitted ?? false,
102
+ };
103
+ }
104
+ /**
105
+ * Compute SHA-256 hash of a file's content.
106
+ *
107
+ * @param filePath - Absolute path to the file
108
+ * @returns Hex-encoded SHA-256 hash
109
+ */
110
+ export async function computeContentHash(filePath) {
111
+ const content = await readFile(filePath);
112
+ return createHash('sha256').update(content).digest('hex');
113
+ }
114
+ //# sourceMappingURL=detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/change-detection/detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,WAAmB;IACjD,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACnC,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB;IACxD,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,UAAkB,EAClB,UAAkC,EAAE;IAEpC,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACnC,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,gDAAgD;IAChD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC;QAC1B,eAAe;QACf,IAAI,EAAE,4CAA4C;QAClD,UAAU;QACV,MAAM;KACP,CAAC,CAAC;IAEH,oBAAoB;IACpB,yDAAyD;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEtE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAE/B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qCAAqC;QAE/E,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACvD,CAAC;aAAM,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACtD,CAAC;aAAM,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,6DAA6D;YAC7D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,SAAS;gBACjB,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QAElC,0BAA0B;QAC1B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,4CAA4C;QAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa;QACb,UAAU;QACV,OAAO;QACP,mBAAmB,EAAE,OAAO,CAAC,kBAAkB,IAAI,KAAK;KACzD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Change detection module
3
+ *
4
+ * Provides git-based change detection for incremental updates.
5
+ * Detects added, modified, deleted, and renamed files.
6
+ */
7
+ export { isGitRepo, getCurrentCommit, getChangedFiles, computeContentHash, } from './detector.js';
8
+ export type { ChangeType, FileChange, ChangeDetectionResult, ChangeDetectionOptions, } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/change-detection/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,UAAU,EACV,UAAU,EACV,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Change detection module
3
+ *
4
+ * Provides git-based change detection for incremental updates.
5
+ * Detects added, modified, deleted, and renamed files.
6
+ */
7
+ export { isGitRepo, getCurrentCommit, getChangedFiles, computeContentHash, } from './detector.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/change-detection/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Types for git change detection
3
+ */
4
+ /**
5
+ * Type of change detected for a file
6
+ */
7
+ export type ChangeType = 'added' | 'modified' | 'deleted' | 'renamed';
8
+ /**
9
+ * A file change detected from git diff
10
+ */
11
+ export interface FileChange {
12
+ /** Relative path to the file (new path for renames) */
13
+ path: string;
14
+ /** Type of change */
15
+ status: ChangeType;
16
+ /** Original path for renamed files */
17
+ oldPath?: string;
18
+ }
19
+ /**
20
+ * Result of change detection
21
+ */
22
+ export interface ChangeDetectionResult {
23
+ /** Current commit hash */
24
+ currentCommit: string;
25
+ /** Commit hash we're comparing from */
26
+ baseCommit: string;
27
+ /** List of changed files */
28
+ changes: FileChange[];
29
+ /** Whether uncommitted changes were included */
30
+ includesUncommitted: boolean;
31
+ }
32
+ /**
33
+ * Options for change detection
34
+ */
35
+ export interface ChangeDetectionOptions {
36
+ /** Include uncommitted (staged and working directory) changes */
37
+ includeUncommitted?: boolean;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/change-detection/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,0BAA0B;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,gDAAgD;IAChD,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Types for git change detection
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/change-detection/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `are discover` command - Discover files to analyze
3
+ *
4
+ * Walks a directory tree and applies filters (gitignore, vendor, binary, custom)
5
+ * to identify files suitable for analysis.
6
+ */
7
+ /**
8
+ * Options for the discover command.
9
+ */
10
+ export interface DiscoverOptions {
11
+ /**
12
+ * Suppress output except errors.
13
+ * @default false
14
+ */
15
+ quiet: boolean;
16
+ /**
17
+ * Show each excluded file with reason.
18
+ * @default false
19
+ */
20
+ showExcluded: boolean;
21
+ /**
22
+ * Show verbose output (each file as discovered).
23
+ * Derived: true unless quiet is set.
24
+ * @default true
25
+ */
26
+ verbose: boolean;
27
+ /**
28
+ * Generate GENERATION-PLAN.md file.
29
+ * @default false
30
+ */
31
+ plan: boolean;
32
+ }
33
+ /**
34
+ * Execute the `are discover` command.
35
+ *
36
+ * Discovers files in the target directory, applying all configured filters
37
+ * (gitignore, vendor, binary, custom patterns).
38
+ *
39
+ * @param targetPath - Directory to scan (defaults to current working directory)
40
+ * @param options - Command options
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * await discoverCommand('.', {
45
+ * quiet: false,
46
+ * showExcluded: true,
47
+ * verbose: true,
48
+ * });
49
+ * ```
50
+ */
51
+ export declare function discoverCommand(targetPath: string, options: DiscoverOptions): Promise<void>;
52
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/cli/discover.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CA6Gf"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * `are discover` command - Discover files to analyze
3
+ *
4
+ * Walks a directory tree and applies filters (gitignore, vendor, binary, custom)
5
+ * to identify files suitable for analysis.
6
+ */
7
+ import path from 'node:path';
8
+ import { access, mkdir, writeFile } from 'node:fs/promises';
9
+ import { constants } from 'node:fs';
10
+ import { walkDirectory } from '../discovery/walker.js';
11
+ import { applyFilters, createGitignoreFilter, createVendorFilter, createBinaryFilter, createCustomFilter, } from '../discovery/filters/index.js';
12
+ import { loadConfig } from '../config/loader.js';
13
+ import { createLogger } from '../output/logger.js';
14
+ import { createOrchestrator } from '../generation/orchestrator.js';
15
+ import { buildExecutionPlan, formatExecutionPlanAsMarkdown } from '../generation/executor.js';
16
+ /**
17
+ * Execute the `are discover` command.
18
+ *
19
+ * Discovers files in the target directory, applying all configured filters
20
+ * (gitignore, vendor, binary, custom patterns).
21
+ *
22
+ * @param targetPath - Directory to scan (defaults to current working directory)
23
+ * @param options - Command options
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * await discoverCommand('.', {
28
+ * quiet: false,
29
+ * showExcluded: true,
30
+ * verbose: true,
31
+ * });
32
+ * ```
33
+ */
34
+ export async function discoverCommand(targetPath, options) {
35
+ // Resolve to absolute path (default to cwd)
36
+ const resolvedPath = path.resolve(targetPath || process.cwd());
37
+ // Load configuration (uses defaults if no config file)
38
+ const config = await loadConfig(resolvedPath);
39
+ // Create logger with options derived from CLI flags and config
40
+ const logger = createLogger({
41
+ verbose: options.quiet ? false : (options.verbose ?? config.output.verbose),
42
+ quiet: options.quiet,
43
+ colors: config.output.colors,
44
+ showExcluded: options.showExcluded,
45
+ });
46
+ // Verify target path exists
47
+ try {
48
+ await access(resolvedPath, constants.R_OK);
49
+ }
50
+ catch (err) {
51
+ const error = err;
52
+ if (error.code === 'ENOENT') {
53
+ logger.error(`Directory not found: ${resolvedPath}`);
54
+ process.exit(1);
55
+ }
56
+ if (error.code === 'EACCES' || error.code === 'EPERM') {
57
+ logger.error(`Permission denied: ${resolvedPath}`);
58
+ process.exit(1);
59
+ }
60
+ throw error;
61
+ }
62
+ logger.info(`Discovering files in ${resolvedPath}...`);
63
+ logger.info('');
64
+ // Create filters in order (per DISC requirements)
65
+ const gitignoreFilter = await createGitignoreFilter(resolvedPath);
66
+ const vendorFilter = createVendorFilter(config.exclude.vendorDirs);
67
+ const binaryFilter = createBinaryFilter({
68
+ maxFileSize: config.options.maxFileSize,
69
+ additionalExtensions: config.exclude.binaryExtensions,
70
+ });
71
+ const customFilter = createCustomFilter(config.exclude.patterns, resolvedPath);
72
+ const filters = [gitignoreFilter, vendorFilter, binaryFilter, customFilter];
73
+ // Walk directory
74
+ const files = await walkDirectory({
75
+ cwd: resolvedPath,
76
+ followSymlinks: config.options.followSymlinks,
77
+ });
78
+ // Apply filters
79
+ const result = await applyFilters(files, filters);
80
+ // Log results
81
+ // Make paths relative for cleaner output
82
+ const relativePath = (absPath) => path.relative(resolvedPath, absPath);
83
+ // Show each included file in verbose mode
84
+ for (const file of result.included) {
85
+ logger.file(relativePath(file));
86
+ }
87
+ // Show each excluded file if --show-excluded
88
+ for (const excluded of result.excluded) {
89
+ logger.excluded(relativePath(excluded.path), excluded.reason, excluded.filter);
90
+ }
91
+ // Always show summary (unless quiet)
92
+ logger.summary(result.included.length, result.excluded.length);
93
+ // Generate GENERATION-PLAN.md if --plan flag is set
94
+ if (options.plan) {
95
+ logger.info('');
96
+ logger.info('Generating execution plan...');
97
+ // Create discovery result for orchestrator
98
+ const discoveryResult = {
99
+ files: result.included,
100
+ excluded: result.excluded.map(e => ({ path: e.path, reason: e.reason })),
101
+ };
102
+ // Create orchestrator and build generation plan
103
+ const orchestrator = createOrchestrator(config, resolvedPath, discoveryResult.files.length);
104
+ const generationPlan = await orchestrator.createPlan(discoveryResult);
105
+ // Build execution plan with post-order traversal
106
+ const executionPlan = buildExecutionPlan(generationPlan, resolvedPath);
107
+ // Format as markdown
108
+ const markdown = formatExecutionPlanAsMarkdown(executionPlan);
109
+ // Write to .agents-reverse-engineer/GENERATION-PLAN.md
110
+ const configDir = path.join(resolvedPath, '.agents-reverse-engineer');
111
+ const planPath = path.join(configDir, 'GENERATION-PLAN.md');
112
+ try {
113
+ await mkdir(configDir, { recursive: true });
114
+ await writeFile(planPath, markdown, 'utf8');
115
+ logger.info(`Created ${path.relative(resolvedPath, planPath)}`);
116
+ }
117
+ catch (err) {
118
+ logger.error(`Failed to write plan: ${err.message}`);
119
+ process.exit(1);
120
+ }
121
+ }
122
+ // Exit with code 0 on success
123
+ process.exit(0);
124
+ }
125
+ //# sourceMappingURL=discover.js.map