forgeos 0.1.0-alpha.65 → 0.1.0-alpha.67

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 (284) hide show
  1. package/.npmignore +19 -19
  2. package/AGENTS.md +1 -1
  3. package/CHANGELOG.md +24 -0
  4. package/LICENSE +21 -21
  5. package/README.md +525 -525
  6. package/adapters/java/README.md +68 -68
  7. package/adapters/java/pom.xml +47 -47
  8. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -20
  9. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -16
  10. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -38
  11. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -16
  12. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -4
  13. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -94
  14. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -12
  15. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -11
  16. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -8
  17. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -179
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -121
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -14
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -14
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -6
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -25
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -18
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -36
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -65
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -18
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -6
  28. package/adapters/java-spring-boot-starter/README.md +32 -32
  29. package/adapters/java-spring-boot-starter/pom.xml +49 -49
  30. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -22
  31. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -15
  32. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -16
  33. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -18
  34. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -16
  35. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -104
  36. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -1
  37. package/bin/forge.mjs +38 -38
  38. package/docs/agent-fabric.md +131 -0
  39. package/examples/java-billing/pom.xml +60 -60
  40. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -4
  41. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -11
  42. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -127
  43. package/package.json +5 -4
  44. package/packages/eslint-plugin-forge/index.ts +15 -15
  45. package/packages/eslint-plugin-forge/package.json +10 -10
  46. package/packages/eslint-plugin-forge/src/check-source.ts +95 -95
  47. package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -24
  48. package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -93
  49. package/schemas/agent-fabric/v0.1/control-event.schema.json +281 -281
  50. package/scripts/field-test-forgeos.mjs +1021 -1021
  51. package/src/forge/_generated/releaseManifest.json +1 -1
  52. package/src/forge/_generated/releaseManifest.ts +3 -3
  53. package/src/forge/agent-adapters/index.ts +7 -3
  54. package/src/forge/agent-adapters/types.ts +1 -0
  55. package/src/forge/agent-fabric/attached-snapshot.ts +55 -0
  56. package/src/forge/agent-fabric/attached-task-contract.ts +105 -0
  57. package/src/forge/agent-fabric/attached-task-service.ts +127 -0
  58. package/src/forge/agent-fabric/attached-task-store.ts +109 -0
  59. package/src/forge/agent-fabric/codex-adversarial-review.ts +229 -0
  60. package/src/forge/agent-fabric/codex-sdk-worker.ts +163 -0
  61. package/src/forge/agent-fabric/index.ts +19 -0
  62. package/src/forge/agent-fabric/local-adaptive-digest-worker.mjs +26 -26
  63. package/src/forge/agent-fabric/local-change-review-service.ts +374 -0
  64. package/src/forge/agent-fabric/local-task-server.ts +324 -249
  65. package/src/forge/agent-fabric/managed-environment.ts +205 -0
  66. package/src/forge/agent-fabric/managed-run-contract.ts +102 -0
  67. package/src/forge/agent-fabric/managed-run-service.ts +392 -0
  68. package/src/forge/agent-fabric/managed-run-store.ts +135 -0
  69. package/src/forge/agent-fabric/managed-workspace.ts +214 -0
  70. package/src/forge/agent-fabric/readiness.ts +26 -0
  71. package/src/forge/agent-fabric/workflow-engine.ts +218 -0
  72. package/src/forge/agent-fabric/workflow-task-actions.ts +104 -0
  73. package/src/forge/agent-fabric/workflow-templates.ts +11 -0
  74. package/src/forge/agent-memory/bridge.ts +309 -47
  75. package/src/forge/agent-memory/context-pack.ts +8 -1
  76. package/src/forge/agent-memory/hook-runner.ts +38 -19
  77. package/src/forge/agent-memory/mcp.ts +500 -286
  78. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +343 -234
  79. package/src/forge/agent-memory/sources/codex.ts +49 -7
  80. package/src/forge/agent-memory/types.ts +11 -0
  81. package/src/forge/bench.ts +154 -154
  82. package/src/forge/cair/action-journal.ts +61 -61
  83. package/src/forge/cair/action-parser.ts +314 -314
  84. package/src/forge/cair/action-validator.ts +40 -40
  85. package/src/forge/cair/actions.ts +1818 -1818
  86. package/src/forge/cair/format.ts +77 -77
  87. package/src/forge/cair/index.ts +106 -106
  88. package/src/forge/cair/query.ts +478 -478
  89. package/src/forge/cair/snapshot.ts +315 -315
  90. package/src/forge/cair/types.ts +248 -248
  91. package/src/forge/cli/ai.ts +816 -816
  92. package/src/forge/cli/codex-app-server.ts +877 -877
  93. package/src/forge/cli/fabric.ts +205 -131
  94. package/src/forge/cli/index.ts +26 -26
  95. package/src/forge/cli/main.ts +259 -245
  96. package/src/forge/cli/next-actions.ts +23 -23
  97. package/src/forge/cli/parse.ts +3574 -3542
  98. package/src/forge/cli/release.ts +309 -309
  99. package/src/forge/cli/self-host.ts +510 -510
  100. package/src/forge/compiler/ai-registry/parse.ts +219 -219
  101. package/src/forge/compiler/app-graph/classify.ts +10 -10
  102. package/src/forge/compiler/app-graph/dup-symbol.ts +29 -29
  103. package/src/forge/compiler/app-graph/extract.ts +231 -231
  104. package/src/forge/compiler/app-graph/forge-apis.ts +25 -25
  105. package/src/forge/compiler/app-graph/index.ts +11 -11
  106. package/src/forge/compiler/app-graph/module-graph.ts +151 -151
  107. package/src/forge/compiler/app-graph/parser.ts +71 -71
  108. package/src/forge/compiler/app-graph/symbols.ts +48 -48
  109. package/src/forge/compiler/app-graph/types.ts +43 -43
  110. package/src/forge/compiler/app-graph/versions.ts +14 -14
  111. package/src/forge/compiler/cache/index.ts +17 -17
  112. package/src/forge/compiler/cache/key.ts +46 -46
  113. package/src/forge/compiler/cache/scheduler.ts +72 -72
  114. package/src/forge/compiler/cache/store.ts +78 -78
  115. package/src/forge/compiler/classifier/capabilities.ts +64 -64
  116. package/src/forge/compiler/classifier/classify.ts +76 -76
  117. package/src/forge/compiler/classifier/contexts.ts +188 -188
  118. package/src/forge/compiler/classifier/index.ts +18 -18
  119. package/src/forge/compiler/classifier/runtime-matrix.ts +45 -45
  120. package/src/forge/compiler/classifier/secrets.ts +31 -31
  121. package/src/forge/compiler/classifier/signals.ts +95 -95
  122. package/src/forge/compiler/client-sdk/build-manifest.ts +210 -210
  123. package/src/forge/compiler/data-graph/sql/serialize.ts +89 -89
  124. package/src/forge/compiler/data-graph/sql/types.ts +38 -38
  125. package/src/forge/compiler/diagnostics/index.ts +57 -57
  126. package/src/forge/compiler/emitter/artifact-kind.ts +14 -14
  127. package/src/forge/compiler/emitter/barrel.ts +47 -47
  128. package/src/forge/compiler/emitter/constants.ts +7 -7
  129. package/src/forge/compiler/emitter/emit.ts +223 -223
  130. package/src/forge/compiler/emitter/index.ts +24 -24
  131. package/src/forge/compiler/emitter/lock.ts +61 -61
  132. package/src/forge/compiler/external-manifest/registry.ts +205 -205
  133. package/src/forge/compiler/external-manifest/types.ts +91 -91
  134. package/src/forge/compiler/external-manifest/validate.ts +373 -373
  135. package/src/forge/compiler/frontend-graph/build.ts +623 -623
  136. package/src/forge/compiler/guards/artifacts.ts +96 -96
  137. package/src/forge/compiler/guards/check-import-guards.ts +106 -106
  138. package/src/forge/compiler/guards/index.ts +11 -11
  139. package/src/forge/compiler/guards/propagate-contexts.ts +57 -57
  140. package/src/forge/compiler/index.ts +17 -17
  141. package/src/forge/compiler/integration/index.ts +17 -17
  142. package/src/forge/compiler/integration/snapshot.ts +54 -54
  143. package/src/forge/compiler/integration/templates/convex.ts +70 -70
  144. package/src/forge/compiler/orchestrator/discover.ts +214 -214
  145. package/src/forge/compiler/orchestrator/guards.ts +5 -5
  146. package/src/forge/compiler/orchestrator/index.ts +27 -27
  147. package/src/forge/compiler/orchestrator/orphans.ts +51 -51
  148. package/src/forge/compiler/orchestrator/profile.ts +23 -23
  149. package/src/forge/compiler/orchestrator/serialize.ts +979 -979
  150. package/src/forge/compiler/orchestrator/verify.ts +35 -35
  151. package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -33
  152. package/src/forge/compiler/package-graph/checksum.ts +107 -107
  153. package/src/forge/compiler/package-graph/exports-discovery.ts +91 -91
  154. package/src/forge/compiler/package-graph/extract-dts.ts +32 -32
  155. package/src/forge/compiler/package-graph/index.ts +24 -24
  156. package/src/forge/compiler/package-graph/jsdoc.ts +50 -50
  157. package/src/forge/compiler/package-graph/oracle.ts +326 -326
  158. package/src/forge/compiler/package-graph/read-file.ts +21 -21
  159. package/src/forge/compiler/package-graph/resolve.ts +131 -131
  160. package/src/forge/compiler/package-manager/adapter.ts +240 -240
  161. package/src/forge/compiler/package-manager/commands.ts +51 -51
  162. package/src/forge/compiler/package-manager/detect.ts +65 -65
  163. package/src/forge/compiler/package-manager/executor.ts +146 -146
  164. package/src/forge/compiler/package-manager/index.ts +22 -22
  165. package/src/forge/compiler/package-manager/parse-spec.ts +16 -16
  166. package/src/forge/compiler/primitives/compare.ts +26 -26
  167. package/src/forge/compiler/primitives/hash.ts +29 -29
  168. package/src/forge/compiler/primitives/header.ts +43 -43
  169. package/src/forge/compiler/primitives/index.ts +45 -45
  170. package/src/forge/compiler/primitives/paths.ts +24 -24
  171. package/src/forge/compiler/primitives/serialize.ts +66 -66
  172. package/src/forge/compiler/primitives/sort.ts +87 -87
  173. package/src/forge/compiler/recipes/helpers.ts +37 -37
  174. package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -26
  175. package/src/forge/compiler/sandbox/backends/child.ts +123 -123
  176. package/src/forge/compiler/sandbox/backends/docker.ts +173 -173
  177. package/src/forge/compiler/sandbox/index.ts +51 -51
  178. package/src/forge/compiler/sandbox/inspect.ts +143 -143
  179. package/src/forge/compiler/sandbox/inspector-entry.ts +115 -115
  180. package/src/forge/compiler/sandbox/limits.ts +31 -31
  181. package/src/forge/compiler/sandbox/scrub-env.ts +60 -60
  182. package/src/forge/compiler/sandbox/secret-scan.ts +54 -54
  183. package/src/forge/compiler/sandbox/serialize.ts +106 -106
  184. package/src/forge/compiler/sandbox/types.ts +7 -7
  185. package/src/forge/compiler/test-graph/build.ts +285 -285
  186. package/src/forge/compiler/types/app-graph.ts +87 -87
  187. package/src/forge/compiler/types/capability.ts +29 -29
  188. package/src/forge/compiler/types/classification.ts +9 -9
  189. package/src/forge/compiler/types/diagnostic.ts +2 -2
  190. package/src/forge/compiler/types/frontend-graph.ts +81 -81
  191. package/src/forge/compiler/types/import-guards.ts +19 -19
  192. package/src/forge/compiler/types/index.ts +98 -98
  193. package/src/forge/compiler/types/json.ts +3 -3
  194. package/src/forge/compiler/types/lock.ts +37 -37
  195. package/src/forge/compiler/types/runtime-matrix.ts +16 -16
  196. package/src/forge/compiler/types/runtime.ts +30 -30
  197. package/src/forge/compiler/types/sandbox.ts +24 -24
  198. package/src/forge/delta/broker-runner.mjs +5 -0
  199. package/src/forge/delta/broker.ts +429 -0
  200. package/src/forge/delta/classifier.ts +52 -52
  201. package/src/forge/delta/explain.ts +238 -238
  202. package/src/forge/delta/git-observer.ts +24 -0
  203. package/src/forge/delta/ids.ts +40 -40
  204. package/src/forge/delta/index.ts +25 -25
  205. package/src/forge/delta/process-identity.ts +31 -0
  206. package/src/forge/delta/queue-status.ts +190 -0
  207. package/src/forge/delta/redaction.ts +50 -50
  208. package/src/forge/delta/schema.ts +135 -135
  209. package/src/forge/delta/session.ts +142 -142
  210. package/src/forge/delta/status.ts +82 -145
  211. package/src/forge/delta/store.ts +77 -32
  212. package/src/forge/delta/timeline.ts +178 -178
  213. package/src/forge/dev/types.ts +63 -63
  214. package/src/forge/dev/watch.ts +119 -119
  215. package/src/forge/intent/index.ts +509 -509
  216. package/src/forge/make/types.ts +153 -153
  217. package/src/forge/refactor/index.ts +1937 -1937
  218. package/src/forge/refactor/runtime-rename.ts +598 -598
  219. package/src/forge/repair/rules/index.ts +476 -476
  220. package/src/forge/review/types.ts +211 -211
  221. package/src/forge/runtime/db/generated-client.ts +305 -305
  222. package/src/forge/runtime/db/pglite-adapter.ts +33 -11
  223. package/src/forge/runtime/runner/run-entry.ts +236 -236
  224. package/src/forge/version.ts +1 -1
  225. package/templates/agent-workroom/AGENTS.md +29 -29
  226. package/templates/agent-workroom/README.md +34 -34
  227. package/templates/agent-workroom/forge.config.ts +3 -3
  228. package/templates/agent-workroom/package.json +34 -34
  229. package/templates/agent-workroom/pnpm-workspace.yaml +2 -2
  230. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -10
  231. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -61
  232. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -119
  233. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -52
  234. package/templates/agent-workroom/src/forge/schema.ts +54 -54
  235. package/templates/agent-workroom/src/policies.ts +6 -6
  236. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -11
  237. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -63
  238. package/templates/agent-workroom/tsconfig.json +16 -16
  239. package/templates/agent-workroom/web/index.html +13 -13
  240. package/templates/agent-workroom/web/package.json +21 -21
  241. package/templates/agent-workroom/web/src/App.tsx +345 -345
  242. package/templates/agent-workroom/web/src/main.tsx +13 -13
  243. package/templates/agent-workroom/web/src/styles.css +545 -545
  244. package/templates/agent-workroom/web/tsconfig.json +27 -27
  245. package/templates/b2b-support-web/package.json +37 -37
  246. package/templates/b2b-support-web/pnpm-workspace.yaml +2 -2
  247. package/templates/b2b-support-web/web/package.json +21 -21
  248. package/templates/minimal-web/package.json +34 -34
  249. package/templates/minimal-web/pnpm-workspace.yaml +2 -2
  250. package/templates/minimal-web/web/index.html +13 -13
  251. package/templates/minimal-web/web/src/styles.css +190 -190
  252. package/templates/nuxt-web/.vscode/settings.json +14 -14
  253. package/templates/nuxt-web/.yarnrc.yml +1 -1
  254. package/templates/nuxt-web/README.md +30 -30
  255. package/templates/nuxt-web/forge.config.ts +3 -3
  256. package/templates/nuxt-web/package.json +34 -34
  257. package/templates/nuxt-web/pnpm-workspace.yaml +2 -2
  258. package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -11
  259. package/templates/nuxt-web/src/commands/createNote.ts +26 -26
  260. package/templates/nuxt-web/src/forge/schema.ts +12 -12
  261. package/templates/nuxt-web/src/policies.ts +6 -6
  262. package/templates/nuxt-web/src/queries/listNotes.ts +8 -8
  263. package/templates/nuxt-web/src/queries/liveNotes.ts +8 -8
  264. package/templates/nuxt-web/tsconfig.json +17 -17
  265. package/templates/nuxt-web/web/app.vue +67 -67
  266. package/templates/nuxt-web/web/components/LiveNotes.vue +89 -89
  267. package/templates/nuxt-web/web/components/NoteComposer.vue +100 -100
  268. package/templates/nuxt-web/web/composables/forge.ts +13 -13
  269. package/templates/nuxt-web/web/composables/useNotes.ts +24 -24
  270. package/templates/nuxt-web/web/nuxt.config.ts +11 -11
  271. package/templates/nuxt-web/web/package.json +19 -19
  272. package/templates/nuxt-web/web/plugins/forge.client.ts +10 -10
  273. package/templates/nuxt-web/web/plugins/forge.server.ts +10 -10
  274. package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -7
  275. package/templates/nuxt-web/web/tsconfig.json +6 -6
  276. package/templates/vendor-access/.vscode/settings.json +14 -14
  277. package/templates/vendor-access/README.md +30 -30
  278. package/templates/vendor-access/package.json +35 -35
  279. package/templates/vendor-access/pnpm-workspace.yaml +2 -2
  280. package/templates/vendor-access/tsconfig.json +17 -17
  281. package/templates/vendor-access/web/index.html +13 -13
  282. package/templates/vendor-access/web/package.json +21 -21
  283. package/templates/vendor-access/web/src/styles.css +682 -682
  284. package/templates/vendor-access/web/tsconfig.json +18 -18
@@ -1,119 +1,119 @@
1
- import { existsSync } from "node:fs";
2
- import { join, relative } from "node:path";
3
- import { watch, type FSWatcher } from "node:fs";
4
- import { createDiagnostic } from "../compiler/diagnostics/create.ts";
5
- import { FORGE_DEV_WATCH_FAILED } from "../compiler/diagnostics/codes.ts";
6
- import { getSourceRoots } from "../compiler/orchestrator/discover.ts";
7
- import { normalizePath } from "../compiler/primitives/paths.ts";
8
- import type { DevWatchHandle } from "./types.ts";
9
-
10
- const SKIP_PATH_SEGMENTS = ["node_modules", "_generated", ".forge"];
11
- const DEBOUNCE_MS = 400;
12
-
13
- export function shouldSkipWatchPath(absolutePath: string): boolean {
14
- const normalized = absolutePath.replace(/\\/g, "/");
15
- return SKIP_PATH_SEGMENTS.some((segment) =>
16
- normalized === segment ||
17
- normalized.startsWith(`${segment}/`) ||
18
- normalized.includes(`/${segment}/`),
19
- );
20
- }
21
-
22
- export function createDebouncedCallback(
23
- debounceMs: number,
24
- callback: (changedCount: number, changedPaths: string[]) => void | Promise<void>,
25
- ): (incrementOrPath?: number | string) => void {
26
- let pendingChanges = 0;
27
- const pendingPaths = new Set<string>();
28
- let timer: ReturnType<typeof setTimeout> | null = null;
29
-
30
- return (incrementOrPath) => {
31
- if (typeof incrementOrPath === "number") {
32
- pendingChanges += incrementOrPath;
33
- } else {
34
- pendingChanges += 1;
35
- }
36
- if (typeof incrementOrPath === "string") {
37
- pendingPaths.add(incrementOrPath);
38
- }
39
- if (timer !== null) {
40
- clearTimeout(timer);
41
- }
42
- timer = setTimeout(async () => {
43
- const count = pendingChanges;
44
- const paths = [...pendingPaths].sort();
45
- pendingChanges = 0;
46
- pendingPaths.clear();
47
- timer = null;
48
- await callback(count, paths);
49
- }, debounceMs);
50
- };
51
- }
52
-
53
- export function startDevWatch(
54
- workspaceRoot: string,
55
- onRegenerate: (changedCount: number, changedPaths: string[]) => void | Promise<void>,
56
- ): DevWatchHandle {
57
- const roots = getSourceRoots(workspaceRoot);
58
- const watchers: FSWatcher[] = [];
59
- const debounced = createDebouncedCallback(DEBOUNCE_MS, onRegenerate);
60
-
61
- for (const root of roots) {
62
- const absoluteRoot = join(workspaceRoot, root);
63
- if (!existsSync(absoluteRoot)) {
64
- continue;
65
- }
66
-
67
- try {
68
- const watcher = watch(
69
- absoluteRoot,
70
- { recursive: true },
71
- (_eventType, filename) => {
72
- if (!filename) {
73
- debounced();
74
- return;
75
- }
76
-
77
- const absolutePath = join(absoluteRoot, filename.toString());
78
- const relativePath = normalizePath(relative(workspaceRoot, absolutePath));
79
-
80
- if (shouldSkipWatchPath(relativePath)) {
81
- return;
82
- }
83
-
84
- debounced(relativePath);
85
- },
86
- );
87
-
88
- watcher.on("error", (error) => {
89
- console.error(
90
- `[forge dev] watch error: ${createDiagnostic({
91
- severity: "error",
92
- code: FORGE_DEV_WATCH_FAILED,
93
- message: error.message,
94
- }).message}`,
95
- );
96
- });
97
-
98
- watchers.push(watcher);
99
- } catch (error) {
100
- const message =
101
- error instanceof Error ? error.message : "failed to start file watcher";
102
- console.error(
103
- `[forge dev] watch error: ${createDiagnostic({
104
- severity: "error",
105
- code: FORGE_DEV_WATCH_FAILED,
106
- message,
107
- }).message}`,
108
- );
109
- }
110
- }
111
-
112
- return {
113
- stop: () => {
114
- for (const watcher of watchers) {
115
- watcher.close();
116
- }
117
- },
118
- };
119
- }
1
+ import { existsSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { watch, type FSWatcher } from "node:fs";
4
+ import { createDiagnostic } from "../compiler/diagnostics/create.ts";
5
+ import { FORGE_DEV_WATCH_FAILED } from "../compiler/diagnostics/codes.ts";
6
+ import { getSourceRoots } from "../compiler/orchestrator/discover.ts";
7
+ import { normalizePath } from "../compiler/primitives/paths.ts";
8
+ import type { DevWatchHandle } from "./types.ts";
9
+
10
+ const SKIP_PATH_SEGMENTS = ["node_modules", "_generated", ".forge"];
11
+ const DEBOUNCE_MS = 400;
12
+
13
+ export function shouldSkipWatchPath(absolutePath: string): boolean {
14
+ const normalized = absolutePath.replace(/\\/g, "/");
15
+ return SKIP_PATH_SEGMENTS.some((segment) =>
16
+ normalized === segment ||
17
+ normalized.startsWith(`${segment}/`) ||
18
+ normalized.includes(`/${segment}/`),
19
+ );
20
+ }
21
+
22
+ export function createDebouncedCallback(
23
+ debounceMs: number,
24
+ callback: (changedCount: number, changedPaths: string[]) => void | Promise<void>,
25
+ ): (incrementOrPath?: number | string) => void {
26
+ let pendingChanges = 0;
27
+ const pendingPaths = new Set<string>();
28
+ let timer: ReturnType<typeof setTimeout> | null = null;
29
+
30
+ return (incrementOrPath) => {
31
+ if (typeof incrementOrPath === "number") {
32
+ pendingChanges += incrementOrPath;
33
+ } else {
34
+ pendingChanges += 1;
35
+ }
36
+ if (typeof incrementOrPath === "string") {
37
+ pendingPaths.add(incrementOrPath);
38
+ }
39
+ if (timer !== null) {
40
+ clearTimeout(timer);
41
+ }
42
+ timer = setTimeout(async () => {
43
+ const count = pendingChanges;
44
+ const paths = [...pendingPaths].sort();
45
+ pendingChanges = 0;
46
+ pendingPaths.clear();
47
+ timer = null;
48
+ await callback(count, paths);
49
+ }, debounceMs);
50
+ };
51
+ }
52
+
53
+ export function startDevWatch(
54
+ workspaceRoot: string,
55
+ onRegenerate: (changedCount: number, changedPaths: string[]) => void | Promise<void>,
56
+ ): DevWatchHandle {
57
+ const roots = getSourceRoots(workspaceRoot);
58
+ const watchers: FSWatcher[] = [];
59
+ const debounced = createDebouncedCallback(DEBOUNCE_MS, onRegenerate);
60
+
61
+ for (const root of roots) {
62
+ const absoluteRoot = join(workspaceRoot, root);
63
+ if (!existsSync(absoluteRoot)) {
64
+ continue;
65
+ }
66
+
67
+ try {
68
+ const watcher = watch(
69
+ absoluteRoot,
70
+ { recursive: true },
71
+ (_eventType, filename) => {
72
+ if (!filename) {
73
+ debounced();
74
+ return;
75
+ }
76
+
77
+ const absolutePath = join(absoluteRoot, filename.toString());
78
+ const relativePath = normalizePath(relative(workspaceRoot, absolutePath));
79
+
80
+ if (shouldSkipWatchPath(relativePath)) {
81
+ return;
82
+ }
83
+
84
+ debounced(relativePath);
85
+ },
86
+ );
87
+
88
+ watcher.on("error", (error) => {
89
+ console.error(
90
+ `[forge dev] watch error: ${createDiagnostic({
91
+ severity: "error",
92
+ code: FORGE_DEV_WATCH_FAILED,
93
+ message: error.message,
94
+ }).message}`,
95
+ );
96
+ });
97
+
98
+ watchers.push(watcher);
99
+ } catch (error) {
100
+ const message =
101
+ error instanceof Error ? error.message : "failed to start file watcher";
102
+ console.error(
103
+ `[forge dev] watch error: ${createDiagnostic({
104
+ severity: "error",
105
+ code: FORGE_DEV_WATCH_FAILED,
106
+ message,
107
+ }).message}`,
108
+ );
109
+ }
110
+ }
111
+
112
+ return {
113
+ stop: () => {
114
+ for (const watcher of watchers) {
115
+ watcher.close();
116
+ }
117
+ },
118
+ };
119
+ }