forgeos 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (406) hide show
  1. package/.npmignore +4 -0
  2. package/AGENTS.md +168 -81
  3. package/CHANGELOG.md +211 -0
  4. package/README.md +88 -14
  5. package/adapters/go/README.md +23 -0
  6. package/adapters/go/go.mod +3 -0
  7. package/adapters/go/http.go +149 -0
  8. package/adapters/go/registry.go +234 -0
  9. package/adapters/go/types.go +136 -0
  10. package/adapters/java/README.md +68 -0
  11. package/adapters/java/pom.xml +34 -0
  12. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
  13. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
  14. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
  15. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
  16. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
  17. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
  28. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
  29. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
  30. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
  31. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
  32. package/adapters/java/target/classes/dev/forgeos/adapter/Auth.class +0 -0
  33. package/adapters/java/target/classes/dev/forgeos/adapter/Diagnostic.class +0 -0
  34. package/adapters/java/target/classes/dev/forgeos/adapter/Entry.class +0 -0
  35. package/adapters/java/target/classes/dev/forgeos/adapter/EntryKind.class +0 -0
  36. package/adapters/java/target/classes/dev/forgeos/adapter/ErrorInfo.class +0 -0
  37. package/adapters/java/target/classes/dev/forgeos/adapter/Forge.class +0 -0
  38. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeCall.class +0 -0
  39. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeContext.class +0 -0
  40. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHandler.class +0 -0
  41. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHttpHandler.class +0 -0
  42. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$EntryOption.class +0 -0
  43. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegisteredEntry.class +0 -0
  44. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegistryOption.class +0 -0
  45. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry.class +0 -0
  46. package/adapters/java/target/classes/dev/forgeos/adapter/Json.class +0 -0
  47. package/adapters/java/target/classes/dev/forgeos/adapter/Manifest.class +0 -0
  48. package/adapters/java/target/classes/dev/forgeos/adapter/RequestEnvelope.class +0 -0
  49. package/adapters/java/target/classes/dev/forgeos/adapter/ResponseEnvelope.class +0 -0
  50. package/adapters/java/target/classes/dev/forgeos/adapter/Risk.class +0 -0
  51. package/adapters/java/target/classes/dev/forgeos/adapter/Schemas.class +0 -0
  52. package/adapters/java/target/classes/dev/forgeos/adapter/Service.class +0 -0
  53. package/adapters/java/target/classes/dev/forgeos/adapter/TransactionMode.class +0 -0
  54. package/adapters/java/target/classes/dev/forgeos/adapter/TypedForgeHandler.class +0 -0
  55. package/adapters/java/target/forge-java-adapter-0.1.0-alpha.11.jar +0 -0
  56. package/adapters/java/target/maven-archiver/pom.properties +3 -0
  57. package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +23 -0
  58. package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +20 -0
  59. package/adapters/java-spring-boot-starter/README.md +32 -0
  60. package/adapters/java-spring-boot-starter/pom.xml +36 -0
  61. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
  62. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
  63. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
  64. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
  65. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
  66. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
  67. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  68. package/adapters/java-spring-boot-starter/target/classes/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  69. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeCommand.class +0 -0
  70. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeExternalService.class +0 -0
  71. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeQuery.class +0 -0
  72. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.class +0 -0
  73. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.class +0 -0
  74. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringRuntime.class +0 -0
  75. package/adapters/java-spring-boot-starter/target/forge-java-spring-boot-starter-0.1.0-alpha.11.jar +0 -0
  76. package/adapters/java-spring-boot-starter/target/maven-archiver/pom.properties +3 -0
  77. package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +6 -0
  78. package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +6 -0
  79. package/bin/forge.mjs +18 -0
  80. package/docs/changelog.md +242 -0
  81. package/docs/forge-protocol.md +189 -0
  82. package/examples/go-billing/go.mod +7 -0
  83. package/examples/go-billing/main.go +120 -0
  84. package/examples/java-billing/pom.xml +52 -0
  85. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
  86. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
  87. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
  88. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/CreateInvoiceInput.class +0 -0
  89. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Invoice.class +0 -0
  90. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$EmptyInput.class +0 -0
  91. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$Options.class +0 -0
  92. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main.class +0 -0
  93. package/examples/java-billing/target/java-billing-0.1.0-alpha.11-all.jar +0 -0
  94. package/examples/java-billing/target/java-billing-0.1.0-alpha.11.jar +0 -0
  95. package/examples/java-billing/target/maven-archiver/pom.properties +3 -0
  96. package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +5 -0
  97. package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +3 -0
  98. package/package.json +29 -7
  99. package/schemas/forge-manifest.schema.json +57 -0
  100. package/src/forge/_generated/releaseManifest.json +1 -2
  101. package/src/forge/_generated/releaseManifest.ts +3 -3
  102. package/src/forge/agent-adapters/index.ts +1511 -123
  103. package/src/forge/agent-adapters/types.ts +216 -1
  104. package/src/forge/agent-memory/bridge.ts +1245 -0
  105. package/src/forge/agent-memory/context-pack.ts +151 -0
  106. package/src/forge/agent-memory/hook-runner.ts +312 -0
  107. package/src/forge/agent-memory/mcp.ts +224 -0
  108. package/src/forge/agent-memory/normalize.ts +498 -0
  109. package/src/forge/agent-memory/redaction.ts +103 -0
  110. package/src/forge/agent-memory/sources/claude-code.ts +51 -0
  111. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
  112. package/src/forge/agent-memory/sources/codex.ts +119 -0
  113. package/src/forge/agent-memory/sources/cursor.ts +35 -0
  114. package/src/forge/agent-memory/types.ts +191 -0
  115. package/src/forge/bench.ts +248 -0
  116. package/src/forge/brownfield-import/index.ts +801 -0
  117. package/src/forge/brownfield-import/types.ts +127 -0
  118. package/src/forge/cair/action-journal.ts +61 -0
  119. package/src/forge/cair/action-parser.ts +314 -0
  120. package/src/forge/cair/action-validator.ts +40 -0
  121. package/src/forge/cair/actions.ts +1818 -0
  122. package/src/forge/cair/format.ts +77 -0
  123. package/src/forge/cair/index.ts +106 -0
  124. package/src/forge/cair/query.ts +478 -0
  125. package/src/forge/cair/snapshot.ts +315 -0
  126. package/src/forge/cair/types.ts +248 -0
  127. package/src/forge/cli/ai.ts +671 -3
  128. package/src/forge/cli/auth.ts +36 -1
  129. package/src/forge/cli/build.ts +20 -4
  130. package/src/forge/cli/changed.ts +300 -0
  131. package/src/forge/cli/codex-app-server.ts +877 -0
  132. package/src/forge/cli/commands.ts +1285 -7
  133. package/src/forge/cli/db.ts +121 -2
  134. package/src/forge/cli/deps.ts +79 -12
  135. package/src/forge/cli/dev.ts +502 -38
  136. package/src/forge/cli/docs.ts +265 -0
  137. package/src/forge/cli/handoff.ts +250 -0
  138. package/src/forge/cli/index.ts +1 -0
  139. package/src/forge/cli/main.ts +49 -3
  140. package/src/forge/cli/new.ts +3 -1
  141. package/src/forge/cli/next-actions.ts +23 -0
  142. package/src/forge/cli/output.ts +290 -1
  143. package/src/forge/cli/parse.ts +770 -36
  144. package/src/forge/cli/query.ts +32 -0
  145. package/src/forge/cli/release.ts +35 -11
  146. package/src/forge/cli/rls.ts +568 -17
  147. package/src/forge/cli/run.ts +41 -0
  148. package/src/forge/cli/secrets.ts +46 -1
  149. package/src/forge/cli/security.ts +381 -0
  150. package/src/forge/cli/self-host.ts +56 -14
  151. package/src/forge/cli/studio.ts +2163 -0
  152. package/src/forge/cli/verify.ts +1422 -32
  153. package/src/forge/compiler/agent-contract/build.ts +725 -41
  154. package/src/forge/compiler/agent-contract/types.ts +85 -0
  155. package/src/forge/compiler/ai-registry/build.ts +62 -1
  156. package/src/forge/compiler/ai-registry/constants.ts +1 -1
  157. package/src/forge/compiler/ai-registry/parse.ts +168 -5
  158. package/src/forge/compiler/api-surface/build.ts +47 -0
  159. package/src/forge/compiler/app-graph/build.ts +68 -8
  160. package/src/forge/compiler/app-graph/extract.ts +107 -0
  161. package/src/forge/compiler/app-graph/forge-apis.ts +1 -0
  162. package/src/forge/compiler/app-graph/module-graph.ts +73 -78
  163. package/src/forge/compiler/app-graph/parser.ts +24 -24
  164. package/src/forge/compiler/app-graph/profile.ts +26 -0
  165. package/src/forge/compiler/app-graph/versions.ts +1 -1
  166. package/src/forge/compiler/classifier/capabilities.ts +3 -2
  167. package/src/forge/compiler/classifier/classify.ts +32 -8
  168. package/src/forge/compiler/classifier/secrets.ts +3 -2
  169. package/src/forge/compiler/classifier/signals.ts +91 -1
  170. package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
  171. package/src/forge/compiler/client-sdk/render-client.ts +188 -13
  172. package/src/forge/compiler/data-graph/parse.ts +3 -3
  173. package/src/forge/compiler/data-graph/sql/ddl.ts +60 -2
  174. package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
  175. package/src/forge/compiler/data-graph/sql/types.ts +1 -0
  176. package/src/forge/compiler/dev-manifest/build.ts +3 -0
  177. package/src/forge/compiler/diagnostics/codes.ts +35 -0
  178. package/src/forge/compiler/diagnostics/create.ts +8 -3
  179. package/src/forge/compiler/diagnostics/index.ts +2 -0
  180. package/src/forge/compiler/emitter/barrel.ts +3 -0
  181. package/src/forge/compiler/emitter/render.ts +5 -0
  182. package/src/forge/compiler/external-manifest/registry.ts +205 -0
  183. package/src/forge/compiler/external-manifest/types.ts +91 -0
  184. package/src/forge/compiler/external-manifest/validate.ts +373 -0
  185. package/src/forge/compiler/frontend-graph/build.ts +85 -13
  186. package/src/forge/compiler/integration/add.ts +498 -22
  187. package/src/forge/compiler/integration/snapshot.ts +2 -0
  188. package/src/forge/compiler/make-registry/build.ts +19 -7
  189. package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
  190. package/src/forge/compiler/orchestrator/plan.ts +78 -7
  191. package/src/forge/compiler/orchestrator/profile.ts +65 -0
  192. package/src/forge/compiler/orchestrator/run.ts +97 -31
  193. package/src/forge/compiler/orchestrator/serialize.ts +101 -8
  194. package/src/forge/compiler/package-graph/compiler.ts +13 -3
  195. package/src/forge/compiler/package-manager/adapter.ts +4 -1
  196. package/src/forge/compiler/package-manager/commands.ts +4 -0
  197. package/src/forge/compiler/package-manager/executor.ts +30 -1
  198. package/src/forge/compiler/policy-registry/build.ts +44 -1
  199. package/src/forge/compiler/test-graph/build.ts +11 -3
  200. package/src/forge/compiler/types/ai-registry.ts +25 -1
  201. package/src/forge/compiler/types/app-graph.ts +9 -2
  202. package/src/forge/compiler/types/cli.ts +76 -1
  203. package/src/forge/compiler/types/dev-manifest.ts +3 -0
  204. package/src/forge/compiler/types/frontend-graph.ts +2 -2
  205. package/src/forge/delta/classifier.ts +52 -0
  206. package/src/forge/delta/explain.ts +126 -0
  207. package/src/forge/delta/git-observer.ts +43 -0
  208. package/src/forge/delta/ids.ts +44 -0
  209. package/src/forge/delta/index.ts +13 -0
  210. package/src/forge/delta/recorder.ts +402 -0
  211. package/src/forge/delta/redaction.ts +50 -0
  212. package/src/forge/delta/schema.ts +240 -0
  213. package/src/forge/delta/session.ts +142 -0
  214. package/src/forge/delta/status.ts +489 -0
  215. package/src/forge/delta/store.ts +2975 -0
  216. package/src/forge/delta/timeline.ts +104 -0
  217. package/src/forge/dev/server.ts +768 -15
  218. package/src/forge/dev/types.ts +15 -1
  219. package/src/forge/dev/watch.ts +17 -7
  220. package/src/forge/dev-console/cycle.ts +233 -21
  221. package/src/forge/dev-console/types.ts +46 -1
  222. package/src/forge/impact/index.ts +46 -8
  223. package/src/forge/impact/types.ts +6 -0
  224. package/src/forge/intent/index.ts +35 -16
  225. package/src/forge/make/index.ts +149 -6
  226. package/src/forge/make/templates.ts +343 -2
  227. package/src/forge/make/types.ts +3 -1
  228. package/src/forge/refactor/index.ts +1 -0
  229. package/src/forge/repair/rules/index.ts +2 -2
  230. package/src/forge/review/index.ts +158 -12
  231. package/src/forge/review/types.ts +15 -0
  232. package/src/forge/runtime/ai/context.ts +210 -5
  233. package/src/forge/runtime/ai/types.ts +70 -0
  234. package/src/forge/runtime/auth/claims.ts +32 -0
  235. package/src/forge/runtime/auth/errors.ts +2 -0
  236. package/src/forge/runtime/context/create-context.ts +30 -6
  237. package/src/forge/runtime/db/generated-client.ts +13 -2
  238. package/src/forge/runtime/db/memory-adapter.ts +2 -2
  239. package/src/forge/runtime/db/pglite-adapter.ts +77 -2
  240. package/src/forge/runtime/db/postgres-adapter.ts +6 -3
  241. package/src/forge/runtime/executor.ts +112 -2
  242. package/src/forge/runtime/external/bridge.ts +649 -0
  243. package/src/forge/runtime/runner/run-entry.ts +16 -7
  244. package/src/forge/runtime/telemetry/scrubber.ts +91 -10
  245. package/src/forge/runtime/webhooks/security.ts +184 -0
  246. package/src/forge/server.ts +100 -2
  247. package/src/forge/version.ts +1 -1
  248. package/src/forge/vue/index.ts +407 -0
  249. package/src/forge/workspace/change-summary.ts +209 -0
  250. package/src/forge/workspace/forge-cli.ts +14 -0
  251. package/src/forge/workspace/git-summary.ts +279 -0
  252. package/templates/agent-workroom/AGENTS.md +29 -0
  253. package/templates/agent-workroom/README.md +34 -0
  254. package/templates/agent-workroom/forge.config.ts +3 -0
  255. package/templates/agent-workroom/package.json +33 -0
  256. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
  257. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
  258. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
  259. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
  260. package/templates/agent-workroom/src/forge/schema.ts +54 -0
  261. package/templates/agent-workroom/src/policies.ts +6 -0
  262. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
  263. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
  264. package/templates/agent-workroom/tsconfig.json +16 -0
  265. package/templates/agent-workroom/web/index.html +12 -0
  266. package/templates/agent-workroom/web/package.json +21 -0
  267. package/templates/agent-workroom/web/src/App.tsx +345 -0
  268. package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
  269. package/templates/agent-workroom/web/src/main.tsx +13 -0
  270. package/templates/agent-workroom/web/src/styles.css +545 -0
  271. package/templates/agent-workroom/web/tsconfig.json +27 -0
  272. package/templates/b2b-support-web/package.json +2 -0
  273. package/templates/b2b-support-web/tsconfig.json +4 -1
  274. package/templates/b2b-support-web/web/package.json +1 -1
  275. package/templates/minimal-web/package.json +2 -1
  276. package/templates/minimal-web/tsconfig.json +3 -1
  277. package/templates/minimal-web/web/package.json +2 -2
  278. package/src/forge/_generated/actionSubscriptions.json +0 -2
  279. package/src/forge/_generated/actionSubscriptions.ts +0 -10
  280. package/src/forge/_generated/agentAdapterManifest.json +0 -2
  281. package/src/forge/_generated/agentAdapterManifest.ts +0 -73
  282. package/src/forge/_generated/agentContract.json +0 -2
  283. package/src/forge/_generated/agentContract.ts +0 -7696
  284. package/src/forge/_generated/agentQuickstart.md +0 -32
  285. package/src/forge/_generated/aiContext.ts +0 -59
  286. package/src/forge/_generated/aiModels.json +0 -2
  287. package/src/forge/_generated/aiModels.ts +0 -35
  288. package/src/forge/_generated/aiProviders.json +0 -2
  289. package/src/forge/_generated/aiProviders.ts +0 -23
  290. package/src/forge/_generated/aiRegistry.json +0 -2
  291. package/src/forge/_generated/aiRegistry.ts +0 -29
  292. package/src/forge/_generated/api.json +0 -2
  293. package/src/forge/_generated/api.ts +0 -8
  294. package/src/forge/_generated/appGraph.json +0 -2
  295. package/src/forge/_generated/appGraph.ts +0 -14667
  296. package/src/forge/_generated/appMap.md +0 -35
  297. package/src/forge/_generated/artifactManifest.json +0 -2
  298. package/src/forge/_generated/artifactManifest.ts +0 -7
  299. package/src/forge/_generated/authClaims.json +0 -2
  300. package/src/forge/_generated/authClaims.ts +0 -13
  301. package/src/forge/_generated/authConfig.json +0 -2
  302. package/src/forge/_generated/authConfig.ts +0 -17
  303. package/src/forge/_generated/authContext.ts +0 -23
  304. package/src/forge/_generated/authRegistry.json +0 -2
  305. package/src/forge/_generated/authRegistry.ts +0 -25
  306. package/src/forge/_generated/buildInfo.json +0 -2
  307. package/src/forge/_generated/buildInfo.ts +0 -9
  308. package/src/forge/_generated/capabilityMap.json +0 -2
  309. package/src/forge/_generated/capabilityMap.md +0 -15
  310. package/src/forge/_generated/capabilityMap.ts +0 -17
  311. package/src/forge/_generated/client.ts +0 -282
  312. package/src/forge/_generated/clientApi.ts +0 -9
  313. package/src/forge/_generated/clientManifest.json +0 -2
  314. package/src/forge/_generated/clientManifest.ts +0 -39
  315. package/src/forge/_generated/clientTypes.ts +0 -78
  316. package/src/forge/_generated/configRegistry.json +0 -2
  317. package/src/forge/_generated/configRegistry.ts +0 -4
  318. package/src/forge/_generated/dataGraph.json +0 -2
  319. package/src/forge/_generated/dataGraph.ts +0 -8
  320. package/src/forge/_generated/db.json +0 -2
  321. package/src/forge/_generated/db.ts +0 -2
  322. package/src/forge/_generated/dbSecurityManifest.json +0 -2
  323. package/src/forge/_generated/dbSecurityManifest.ts +0 -15
  324. package/src/forge/_generated/dbSessionContext.json +0 -2
  325. package/src/forge/_generated/dbSessionContext.ts +0 -39
  326. package/src/forge/_generated/deployManifest.json +0 -2
  327. package/src/forge/_generated/deployManifest.ts +0 -14
  328. package/src/forge/_generated/devManifest.json +0 -2
  329. package/src/forge/_generated/devManifest.ts +0 -47
  330. package/src/forge/_generated/envSchema.json +0 -2
  331. package/src/forge/_generated/envSchema.ts +0 -59
  332. package/src/forge/_generated/frontendGraph.json +0 -2
  333. package/src/forge/_generated/frontendGraph.ts +0 -27
  334. package/src/forge/_generated/importGuards.json +0 -2
  335. package/src/forge/_generated/importGuards.ts +0 -686
  336. package/src/forge/_generated/index.ts +0 -67
  337. package/src/forge/_generated/liveProductionManifest.json +0 -2
  338. package/src/forge/_generated/liveProductionManifest.ts +0 -23
  339. package/src/forge/_generated/liveProtocol.json +0 -2
  340. package/src/forge/_generated/liveProtocol.ts +0 -21
  341. package/src/forge/_generated/liveQueryRegistry.json +0 -2
  342. package/src/forge/_generated/liveQueryRegistry.ts +0 -9
  343. package/src/forge/_generated/liveTransportConfig.json +0 -2
  344. package/src/forge/_generated/liveTransportConfig.ts +0 -19
  345. package/src/forge/_generated/makeRegistry.json +0 -2
  346. package/src/forge/_generated/makeRegistry.ts +0 -163
  347. package/src/forge/_generated/makeTemplates.json +0 -2
  348. package/src/forge/_generated/makeTemplates.ts +0 -61
  349. package/src/forge/_generated/mockMap.json +0 -2
  350. package/src/forge/_generated/mockMap.ts +0 -7
  351. package/src/forge/_generated/operationPlaybooks.md +0 -147
  352. package/src/forge/_generated/packageGraph.json +0 -2
  353. package/src/forge/_generated/packageGraph.ts +0 -245249
  354. package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
  355. package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
  356. package/src/forge/_generated/permissionMatrix.json +0 -2
  357. package/src/forge/_generated/permissionMatrix.ts +0 -7
  358. package/src/forge/_generated/policyRegistry.json +0 -2
  359. package/src/forge/_generated/policyRegistry.ts +0 -11
  360. package/src/forge/_generated/queryRegistry.json +0 -2
  361. package/src/forge/_generated/queryRegistry.ts +0 -9
  362. package/src/forge/_generated/react.d.ts +0 -22
  363. package/src/forge/_generated/react.ts +0 -29
  364. package/src/forge/_generated/reactManifest.json +0 -2
  365. package/src/forge/_generated/reactManifest.ts +0 -19
  366. package/src/forge/_generated/rlsPolicies.json +0 -2
  367. package/src/forge/_generated/rlsPolicies.sql +0 -34
  368. package/src/forge/_generated/rlsPolicies.ts +0 -6
  369. package/src/forge/_generated/runtimeGraph.json +0 -2
  370. package/src/forge/_generated/runtimeGraph.ts +0 -8
  371. package/src/forge/_generated/runtimeMatrix.json +0 -2
  372. package/src/forge/_generated/runtimeMatrix.ts +0 -327385
  373. package/src/forge/_generated/runtimeRegistry.ts +0 -2
  374. package/src/forge/_generated/runtimeRules.md +0 -79
  375. package/src/forge/_generated/secretRegistry.json +0 -2
  376. package/src/forge/_generated/secretRegistry.ts +0 -50
  377. package/src/forge/_generated/secretsContext.ts +0 -11
  378. package/src/forge/_generated/serverApi.ts +0 -10
  379. package/src/forge/_generated/sourceMapManifest.json +0 -2
  380. package/src/forge/_generated/sourceMapManifest.ts +0 -7
  381. package/src/forge/_generated/sqlPlan.json +0 -2
  382. package/src/forge/_generated/sqlPlan.ts +0 -88
  383. package/src/forge/_generated/subscriptionManifest.json +0 -2
  384. package/src/forge/_generated/subscriptionManifest.ts +0 -7
  385. package/src/forge/_generated/symbolicationManifest.json +0 -2
  386. package/src/forge/_generated/symbolicationManifest.ts +0 -17
  387. package/src/forge/_generated/telemetryRegistry.json +0 -2
  388. package/src/forge/_generated/telemetryRegistry.ts +0 -9
  389. package/src/forge/_generated/telemetrySinks.json +0 -2
  390. package/src/forge/_generated/telemetrySinks.ts +0 -11
  391. package/src/forge/_generated/tenantScope.json +0 -2
  392. package/src/forge/_generated/tenantScope.ts +0 -8
  393. package/src/forge/_generated/testGraph.json +0 -2
  394. package/src/forge/_generated/testGraph.ts +0 -3108
  395. package/src/forge/_generated/testPlanRegistry.json +0 -2
  396. package/src/forge/_generated/testPlanRegistry.ts +0 -33
  397. package/src/forge/_generated/uiRoutes.json +0 -2
  398. package/src/forge/_generated/uiRoutes.ts +0 -16
  399. package/src/forge/_generated/uiScenarios.json +0 -2
  400. package/src/forge/_generated/uiScenarios.ts +0 -30
  401. package/src/forge/_generated/uiTestManifest.json +0 -2
  402. package/src/forge/_generated/uiTestManifest.ts +0 -27
  403. package/src/forge/_generated/workflowRegistry.json +0 -2
  404. package/src/forge/_generated/workflowRegistry.ts +0 -9
  405. package/src/forge/_generated/workflowSubscriptions.json +0 -2
  406. package/src/forge/_generated/workflowSubscriptions.ts +0 -10
@@ -1,5 +1,6 @@
1
1
  import type { SyntaxNode } from "tree-sitter";
2
2
  import { classifyForgeCallee } from "./classify.ts";
3
+ import type { ForgeKind } from "../types/app-graph.ts";
3
4
  import type { RawSymbol } from "./types.ts";
4
5
 
5
6
  export interface SymbolNameInfo {
@@ -87,7 +88,113 @@ export function extractSymbolsFromTree(
87
88
  const symbols: RawSymbol[] = [];
88
89
  const visited = new Set<string>();
89
90
 
91
+ function record(
92
+ kind: ForgeKind,
93
+ name: string,
94
+ qualifiedName: string,
95
+ node: SyntaxNode,
96
+ exportPath: string,
97
+ ): void {
98
+ const key = `${kind}:${qualifiedName}:${node.startIndex}:${node.endIndex}`;
99
+ if (visited.has(key)) {
100
+ return;
101
+ }
102
+ visited.add(key);
103
+ symbols.push({
104
+ kind,
105
+ name,
106
+ qualifiedName,
107
+ file,
108
+ span: { start: node.startIndex, end: node.endIndex },
109
+ exportPath,
110
+ sourceSlice: source.slice(node.startIndex, node.endIndex),
111
+ });
112
+ }
113
+
114
+ function symbolNameForDeclaration(node: SyntaxNode): string | null {
115
+ const nameNode = node.childForFieldName("name");
116
+ if (
117
+ nameNode?.type === "identifier" ||
118
+ nameNode?.type === "type_identifier"
119
+ ) {
120
+ return nameNode.text;
121
+ }
122
+ return null;
123
+ }
124
+
125
+ function codeDeclarationKind(node: SyntaxNode): ForgeKind | null {
126
+ if (node.type === "function_declaration") return "code.function";
127
+ if (node.type === "class_declaration") return "code.class";
128
+ if (node.type === "interface_declaration") return "code.interface";
129
+ if (node.type === "type_alias_declaration") return "code.type";
130
+ if (node.type === "enum_declaration") return "code.enum";
131
+ return null;
132
+ }
133
+
134
+ function isProgramLevel(node: SyntaxNode): boolean {
135
+ return node.parent?.type === "program" ||
136
+ (node.parent?.type === "export_statement" && node.parent.parent?.type === "program");
137
+ }
138
+
139
+ function exportPathForNode(node: SyntaxNode): string {
140
+ return node.parent?.type === "export_statement" ? "export" : "";
141
+ }
142
+
143
+ function resolveVariableInitializerCallee(declarator: SyntaxNode): string | null {
144
+ const value = declarator.childForFieldName("value");
145
+ if (value?.type !== "call_expression") {
146
+ return null;
147
+ }
148
+ const functionNode = value.childForFieldName("function");
149
+ return functionNode?.type === "identifier" ? resolveCalleeName(functionNode) : null;
150
+ }
151
+
152
+ function recordCodeDeclaration(node: SyntaxNode): void {
153
+ if (!isProgramLevel(node)) {
154
+ return;
155
+ }
156
+ const kind = codeDeclarationKind(node);
157
+ if (!kind) {
158
+ return;
159
+ }
160
+ const name = symbolNameForDeclaration(node);
161
+ if (!name) {
162
+ return;
163
+ }
164
+ record(kind, name, name, node, exportPathForNode(node));
165
+ }
166
+
167
+ function recordCodeVariables(node: SyntaxNode): void {
168
+ if (
169
+ node.type !== "lexical_declaration" &&
170
+ node.type !== "variable_declaration"
171
+ ) {
172
+ return;
173
+ }
174
+ if (!isProgramLevel(node)) {
175
+ return;
176
+ }
177
+
178
+ for (const declarator of node.namedChildren) {
179
+ if (declarator.type !== "variable_declarator") {
180
+ continue;
181
+ }
182
+ const nameNode = declarator.childForFieldName("name");
183
+ if (nameNode?.type !== "identifier") {
184
+ continue;
185
+ }
186
+ const callee = resolveVariableInitializerCallee(declarator);
187
+ if (callee && classifyForgeCallee(callee)) {
188
+ continue;
189
+ }
190
+ record("code.const", nameNode.text, nameNode.text, declarator, exportPathForNode(node));
191
+ }
192
+ }
193
+
90
194
  function visit(node: SyntaxNode): void {
195
+ recordCodeDeclaration(node);
196
+ recordCodeVariables(node);
197
+
91
198
  if (node.type === "call_expression") {
92
199
  const functionNode = node.childForFieldName("function");
93
200
  if (functionNode && functionNode.type === "identifier") {
@@ -13,6 +13,7 @@ export const FORGE_BUILDER_APIS: Readonly<Record<string, ForgeKind>> = {
13
13
  definePolicies: "policy",
14
14
  workflow: "workflow",
15
15
  agent: "agent",
16
+ aiTool: "aiTool",
16
17
  telemetryEvent: "telemetryEvent",
17
18
  };
18
19
 
@@ -15,7 +15,6 @@ import type {
15
15
  } from "../types/app-graph.ts";
16
16
  import type { RuntimeContext } from "../types/runtime.ts";
17
17
  import { FORGE_KIND_TO_CONTEXT } from "./forge-apis.ts";
18
- import { loadTsconfig } from "./tsconfig-hash.ts";
19
18
  import type { RawSymbol } from "./types.ts";
20
19
 
21
20
  export function moduleIdForFile(file: string): string {
@@ -57,19 +56,27 @@ function stableSortModuleNodes(nodes: ModuleNode[]): ModuleNode[] {
57
56
 
58
57
  function declaredContextsForFile(
59
58
  file: string,
60
- symbols: RawSymbol[],
59
+ contextsByFile: Map<string, RuntimeContext[]>,
61
60
  ): RuntimeContext[] {
62
- const contexts = new Set<RuntimeContext>();
61
+ return contextsByFile.get(file) ?? [];
62
+ }
63
+
64
+ function buildDeclaredContextsByFile(symbols: RawSymbol[]): Map<string, RuntimeContext[]> {
65
+ const mutable = new Map<string, Set<RuntimeContext>>();
63
66
  for (const symbol of symbols) {
64
- if (symbol.file !== file) {
65
- continue;
66
- }
67
67
  const context = FORGE_KIND_TO_CONTEXT[symbol.kind];
68
68
  if (context) {
69
- contexts.add(context);
69
+ const fileContexts = mutable.get(symbol.file) ?? new Set<RuntimeContext>();
70
+ fileContexts.add(context);
71
+ mutable.set(symbol.file, fileContexts);
70
72
  }
71
73
  }
72
- return stableSortStrings([...contexts]) as RuntimeContext[];
74
+
75
+ const byFile = new Map<string, RuntimeContext[]>();
76
+ for (const [file, fileContexts] of mutable) {
77
+ byFile.set(file, stableSortStrings([...fileContexts]) as RuntimeContext[]);
78
+ }
79
+ return byFile;
73
80
  }
74
81
 
75
82
  function spanFromNode(node: ts.Node, sourceFile: ts.SourceFile): {
@@ -81,50 +88,37 @@ function spanFromNode(node: ts.Node, sourceFile: ts.SourceFile): {
81
88
  return { start, end };
82
89
  }
83
90
 
84
- function toWorkspaceRelativePath(
85
- absoluteOrRelativePath: string,
86
- workspaceRoot: string,
87
- ): string {
88
- const normalized = normalizePath(absoluteOrRelativePath);
89
- const root = normalizePath(path.resolve(workspaceRoot).replace(/\\/g, "/"));
90
- const rootWithSlash = root.endsWith("/") ? root : `${root}/`;
91
-
92
- if (normalized.startsWith(rootWithSlash)) {
93
- return normalized.slice(rootWithSlash.length);
94
- }
95
-
96
- if (normalized === root) {
97
- return "";
98
- }
99
-
100
- return normalized;
101
- }
102
-
103
91
  function resolveLocalTarget(
104
92
  specifier: string,
105
93
  fromFile: string,
106
- program: ts.Program,
107
- workspaceRoot: string,
94
+ sourcePaths: Set<string>,
108
95
  ): string | null {
109
- const resolved = ts.resolveModuleName(
110
- specifier,
111
- fromFile,
112
- program.getCompilerOptions(),
113
- ts.sys,
114
- );
115
-
116
- const fileName = resolved.resolvedModule?.resolvedFileName;
117
- if (!fileName) {
96
+ if (!specifier.startsWith(".")) {
118
97
  return null;
119
98
  }
120
99
 
121
- return toWorkspaceRelativePath(fileName, workspaceRoot);
100
+ const base = normalizePath(path.join(path.dirname(fromFile), specifier));
101
+ const candidates = [
102
+ base,
103
+ `${base}.ts`,
104
+ `${base}.tsx`,
105
+ `${base}/index.ts`,
106
+ `${base}/index.tsx`,
107
+ ];
108
+ if (/\.[cm]?jsx?$/.test(base)) {
109
+ const withoutJsExtension = base.replace(/\.[cm]?jsx?$/, "");
110
+ candidates.push(
111
+ `${withoutJsExtension}.ts`,
112
+ `${withoutJsExtension}.tsx`,
113
+ );
114
+ }
115
+
116
+ return candidates.find((candidate) => sourcePaths.has(candidate)) ?? null;
122
117
  }
123
118
 
124
119
  function collectImports(
125
120
  sourceFile: ts.SourceFile,
126
- program: ts.Program,
127
- workspaceRoot: string,
121
+ sourcePaths: Set<string>,
128
122
  ): { packageImports: PackageImport[]; localImports: LocalImport[] } {
129
123
  const packageImports: PackageImport[] = [];
130
124
  const localImports: LocalImport[] = [];
@@ -132,13 +126,10 @@ function collectImports(
132
126
 
133
127
  function recordPackageImport(
134
128
  specifier: string,
129
+ parsed: { packageName: string; subpath: string },
135
130
  span: { start: number; end: number },
136
131
  importKind: ImportKind,
137
132
  ): void {
138
- const parsed = parsePackageSpecifier(specifier);
139
- if (!parsed) {
140
- return;
141
- }
142
133
  packageImports.push({
143
134
  specifier,
144
135
  packageName: parsed.packageName,
@@ -155,13 +146,12 @@ function collectImports(
155
146
  const span = spanFromNode(node.moduleSpecifier, sourceFile);
156
147
  const parsed = parsePackageSpecifier(specifier);
157
148
  if (parsed) {
158
- recordPackageImport(specifier, span, "static");
149
+ recordPackageImport(specifier, parsed, span, "static");
159
150
  } else {
160
151
  const target = resolveLocalTarget(
161
152
  specifier,
162
153
  fromFile,
163
- program,
164
- workspaceRoot,
154
+ sourcePaths,
165
155
  );
166
156
  if (target) {
167
157
  localImports.push({
@@ -183,13 +173,12 @@ function collectImports(
183
173
  const span = spanFromNode(node.arguments[0], sourceFile);
184
174
  const parsed = parsePackageSpecifier(specifier);
185
175
  if (parsed) {
186
- recordPackageImport(specifier, span, "dynamic");
176
+ recordPackageImport(specifier, parsed, span, "dynamic");
187
177
  } else {
188
178
  const target = resolveLocalTarget(
189
179
  specifier,
190
180
  fromFile,
191
- program,
192
- workspaceRoot,
181
+ sourcePaths,
193
182
  );
194
183
  if (target) {
195
184
  localImports.push({
@@ -211,13 +200,12 @@ function collectImports(
211
200
  const span = spanFromNode(node.arguments[0], sourceFile);
212
201
  const parsed = parsePackageSpecifier(specifier);
213
202
  if (parsed) {
214
- recordPackageImport(specifier, span, "require");
203
+ recordPackageImport(specifier, parsed, span, "require");
215
204
  } else {
216
205
  const target = resolveLocalTarget(
217
206
  specifier,
218
207
  fromFile,
219
- program,
220
- workspaceRoot,
208
+ sourcePaths,
221
209
  );
222
210
  if (target) {
223
211
  localImports.push({
@@ -238,8 +226,9 @@ function collectImports(
238
226
  function sourcesUnchangedSincePrior(
239
227
  sources: SourceFile[],
240
228
  prior?: AppGraph,
229
+ canReusePrior = true,
241
230
  ): boolean {
242
- if (!prior) {
231
+ if (!prior || !canReusePrior) {
243
232
  return false;
244
233
  }
245
234
  const priorHashes = new Map(Object.entries(prior.sourceHashes ?? {}));
@@ -254,39 +243,46 @@ function sourcesUnchangedSincePrior(
254
243
  return true;
255
244
  }
256
245
 
246
+ function priorModuleNodesByFile(prior?: AppGraph): Map<string, ModuleNode> {
247
+ return new Map((prior?.moduleGraph.nodes ?? []).map((node) => [node.file, node]));
248
+ }
249
+
257
250
  export function buildModuleGraph(
258
251
  sources: SourceFile[],
259
252
  rawSymbols: RawSymbol[],
260
- workspaceRoot: string,
261
- tsconfigPath?: string,
262
253
  prior?: AppGraph,
254
+ canReusePrior = true,
263
255
  ): ModuleGraph {
264
- if (sourcesUnchangedSincePrior(sources, prior)) {
256
+ if (sourcesUnchangedSincePrior(sources, prior, canReusePrior)) {
265
257
  return prior!.moduleGraph;
266
258
  }
267
259
 
268
- const parsedConfig = loadTsconfig(workspaceRoot, tsconfigPath);
269
- const fileNames = sources.map((source) =>
270
- path.resolve(workspaceRoot, source.path).replace(/\\/g, "/"),
271
- );
272
-
273
- const program = ts.createProgram(fileNames, {
274
- ...parsedConfig.options,
275
- noEmit: true,
276
- skipLibCheck: true,
277
- });
260
+ const priorHashes = new Map(Object.entries(prior?.sourceHashes ?? {}));
261
+ const priorNodes = priorModuleNodesByFile(prior);
262
+ const contextsByFile = buildDeclaredContextsByFile(rawSymbols);
263
+ const sourcePaths = new Set(sources.map((source) => normalizePath(source.path)));
278
264
 
279
265
  const nodes: ModuleNode[] = [];
280
266
 
281
267
  for (const source of sources) {
282
268
  const normalizedFile = normalizePath(source.path);
283
- const absolutePath = fileNames.find(
284
- (name) => normalizePath(name).endsWith(normalizedFile),
285
- );
269
+ const priorNode = priorNodes.get(normalizedFile);
270
+ if (
271
+ canReusePrior &&
272
+ priorNode &&
273
+ priorHashes.get(normalizedFile) === source.contentHash
274
+ ) {
275
+ nodes.push(priorNode);
276
+ continue;
277
+ }
286
278
 
287
- const sourceFile = absolutePath
288
- ? program.getSourceFile(absolutePath)
289
- : undefined;
279
+ const sourceFile = ts.createSourceFile(
280
+ normalizedFile,
281
+ source.text,
282
+ ts.ScriptTarget.Latest,
283
+ true,
284
+ normalizedFile.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
285
+ );
290
286
 
291
287
  if (!sourceFile) {
292
288
  nodes.push({
@@ -294,7 +290,7 @@ export function buildModuleGraph(
294
290
  file: normalizedFile,
295
291
  directPackageImports: [],
296
292
  localImports: [],
297
- declaredContexts: declaredContextsForFile(normalizedFile, rawSymbols),
293
+ declaredContexts: declaredContextsForFile(normalizedFile, contextsByFile),
298
294
  effectiveContexts: [],
299
295
  });
300
296
  continue;
@@ -302,8 +298,7 @@ export function buildModuleGraph(
302
298
 
303
299
  const { packageImports, localImports } = collectImports(
304
300
  sourceFile,
305
- program,
306
- workspaceRoot,
301
+ sourcePaths,
307
302
  );
308
303
 
309
304
  nodes.push({
@@ -311,7 +306,7 @@ export function buildModuleGraph(
311
306
  file: normalizedFile,
312
307
  directPackageImports: packageImports,
313
308
  localImports,
314
- declaredContexts: declaredContextsForFile(normalizedFile, rawSymbols),
309
+ declaredContexts: declaredContextsForFile(normalizedFile, contextsByFile),
315
310
  effectiveContexts: [],
316
311
  });
317
312
  }
@@ -32,31 +32,30 @@ function priorSymbolsToRaw(symbols: ForgeSymbol[]): RawSymbol[] {
32
32
  }));
33
33
  }
34
34
 
35
+ interface PriorSymbolsForFile {
36
+ contentHash?: string;
37
+ symbols: ForgeSymbol[];
38
+ }
39
+
35
40
  function groupPriorSymbolsByFile(
36
41
  priorSymbols: ForgeSymbol[],
37
- ): Map<string, ForgeSymbol[]> {
38
- const byFile = new Map<string, ForgeSymbol[]>();
42
+ ): Map<string, PriorSymbolsForFile> {
43
+ const byFile = new Map<string, PriorSymbolsForFile>();
39
44
  for (const symbol of priorSymbols) {
40
- const list = byFile.get(symbol.file) ?? [];
41
- list.push(symbol);
42
- byFile.set(symbol.file, list);
45
+ const existing = byFile.get(symbol.file);
46
+ if (existing) {
47
+ existing.symbols.push(symbol);
48
+ continue;
49
+ }
50
+ const fromMeta = symbol.meta.fileContentHash;
51
+ byFile.set(symbol.file, {
52
+ contentHash: typeof fromMeta === "string" ? fromMeta : undefined,
53
+ symbols: [symbol],
54
+ });
43
55
  }
44
56
  return byFile;
45
57
  }
46
58
 
47
- function priorFileContentHash(
48
- priorSymbols: ForgeSymbol[],
49
- file: string,
50
- ): string | undefined {
51
- const match = priorSymbols.find((symbol) => symbol.file === file);
52
- if (!match) {
53
- return undefined;
54
- }
55
- // All symbols from the same file share the same slice hash basis; use meta when present.
56
- const fromMeta = match.meta.fileContentHash;
57
- return typeof fromMeta === "string" ? fromMeta : undefined;
58
- }
59
-
60
59
  export interface IncrementalParseResult {
61
60
  symbols: RawSymbol[];
62
61
  diagnostics: Diagnostic[];
@@ -65,6 +64,7 @@ export interface IncrementalParseResult {
65
64
  export function incrementalParse(
66
65
  sources: SourceFile[],
67
66
  priorSymbols: ForgeSymbol[] | undefined,
67
+ priorSourceHashes: Record<string, string> | undefined,
68
68
  priorInvalidation: ParseInvalidationKey | undefined,
69
69
  currentInvalidation: ParseInvalidationKey,
70
70
  ): IncrementalParseResult {
@@ -76,22 +76,22 @@ export function incrementalParse(
76
76
 
77
77
  const priorByFile = priorSymbols
78
78
  ? groupPriorSymbolsByFile(priorSymbols)
79
- : new Map<string, ForgeSymbol[]>();
79
+ : new Map<string, PriorSymbolsForFile>();
80
80
 
81
81
  for (const source of sources) {
82
82
  const normalizedFile = normalizePath(source.path);
83
83
  const priorForFile = priorByFile.get(normalizedFile);
84
- const priorHash = priorSymbols
85
- ? priorFileContentHash(priorSymbols, normalizedFile)
86
- : undefined;
84
+ const priorHash = priorForFile?.contentHash ?? priorSourceHashes?.[normalizedFile];
87
85
 
88
86
  const fileUnchanged =
89
87
  !globalInvalidated &&
90
- priorForFile !== undefined &&
91
88
  priorHash === source.contentHash;
92
89
 
90
+ if (fileUnchanged && priorForFile) {
91
+ allSymbols.push(...priorSymbolsToRaw(priorForFile.symbols));
92
+ continue;
93
+ }
93
94
  if (fileUnchanged) {
94
- allSymbols.push(...priorSymbolsToRaw(priorForFile));
95
95
  continue;
96
96
  }
97
97
 
@@ -0,0 +1,26 @@
1
+ import type { AppGraph } from "../types/app-graph.ts";
2
+
3
+ export interface AppGraphPhaseTimings {
4
+ normalizeMs: number;
5
+ parseMs: number;
6
+ symbolsMs: number;
7
+ duplicatesMs: number;
8
+ moduleGraphMs: number;
9
+ inputHashMs: number;
10
+ totalMs: number;
11
+ }
12
+
13
+ const appGraphProfiles = new WeakMap<AppGraph, AppGraphPhaseTimings>();
14
+
15
+ export function recordAppGraphProfile(
16
+ graph: AppGraph,
17
+ timings: AppGraphPhaseTimings,
18
+ ): void {
19
+ appGraphProfiles.set(graph, timings);
20
+ }
21
+
22
+ export function getAppGraphProfile(
23
+ graph: AppGraph,
24
+ ): AppGraphPhaseTimings | undefined {
25
+ return appGraphProfiles.get(graph);
26
+ }
@@ -8,7 +8,7 @@ export const APP_GRAPH_ANALYZER_VERSION = "0.1.0";
8
8
  export const TREE_SITTER_GRAMMAR_VERSION = "0.23.2";
9
9
 
10
10
  /** Forge builder API → ForgeKind classifier version. */
11
- export const FORGE_CLASSIFIER_VERSION = "0.1.1";
11
+ export const FORGE_CLASSIFIER_VERSION = "0.1.3";
12
12
 
13
13
  /** Generation orchestrator version (recorded on emitted AppGraph). */
14
14
  export { GENERATOR_VERSION } from "../../version.ts";
@@ -2,17 +2,18 @@ import type { CapabilitySet } from "../types/capability.ts";
2
2
  import type { IntegrationRecipe } from "../types/integration.ts";
3
3
  import type { PackageApi } from "../types/package-graph.ts";
4
4
  import { capability, emptyCapabilitySet } from "../recipes/helpers.ts";
5
- import { gatherSignals } from "./signals.ts";
5
+ import { gatherSignals, type PackageSignals } from "./signals.ts";
6
6
 
7
7
  export function detectCapabilities(
8
8
  api: PackageApi,
9
9
  recipe?: IntegrationRecipe,
10
+ precomputedSignals?: PackageSignals,
10
11
  ): CapabilitySet {
11
12
  if (recipe) {
12
13
  return cloneCapabilitySet(recipe.capabilities);
13
14
  }
14
15
 
15
- const signals = gatherSignals(api);
16
+ const signals = precomputedSignals ?? gatherSignals(api);
16
17
  const caps = emptyCapabilitySet();
17
18
 
18
19
  if (signals.usesNetwork) {
@@ -8,7 +8,7 @@ import { resolveByPackageName } from "../recipes/registry.ts";
8
8
  import { detectCapabilities } from "./capabilities.ts";
9
9
  import { partitionContexts } from "./contexts.ts";
10
10
  import { detectSecrets } from "./secrets.ts";
11
- import { gatherSignals } from "./signals.ts";
11
+ import { gatherSignals, type PackageSignals } from "./signals.ts";
12
12
 
13
13
  export interface RuntimeClassifier {
14
14
  classify(api: PackageApi, recipe?: IntegrationRecipe): RuntimeClassification;
@@ -30,8 +30,8 @@ function classifyExport(
30
30
  recipe: IntegrationRecipe | undefined,
31
31
  caps: CapabilitySet,
32
32
  alias: string,
33
+ signals: PackageSignals,
33
34
  ): ExportClassification {
34
- const signals = gatherSignals(api);
35
35
  const { compatible, incompatible } = partitionContexts(
36
36
  recipe,
37
37
  caps,
@@ -55,12 +55,12 @@ export function classify(
55
55
  recipe?: IntegrationRecipe,
56
56
  ): RuntimeClassification {
57
57
  const resolvedRecipe = resolveRecipeForApi(api, recipe);
58
- const caps = detectCapabilities(api, resolvedRecipe);
58
+ const signals = gatherSignals(api);
59
+ const caps = detectCapabilities(api, resolvedRecipe, signals);
59
60
  const capsWithSecrets: CapabilitySet = {
60
61
  ...caps,
61
- secrets: detectSecrets(api, resolvedRecipe),
62
+ secrets: detectSecrets(api, resolvedRecipe, signals),
62
63
  };
63
- const signals = gatherSignals(api);
64
64
  const alias = resolvedRecipe?.alias ?? api.name;
65
65
 
66
66
  const { compatible, incompatible, rationale } = partitionContexts(
@@ -74,19 +74,43 @@ export function classify(
74
74
  for (const ep of api.entrypoints) {
75
75
  for (const exp of ep.exports) {
76
76
  perEntrypoint.push(
77
- classifyExport(api, ep.subpath, exp.name, resolvedRecipe, capsWithSecrets, alias),
77
+ classifyExport(
78
+ api,
79
+ ep.subpath,
80
+ exp.name,
81
+ resolvedRecipe,
82
+ capsWithSecrets,
83
+ alias,
84
+ signals,
85
+ ),
78
86
  );
79
87
  }
80
88
  if (ep.exports.length === 0) {
81
89
  perEntrypoint.push(
82
- classifyExport(api, ep.subpath, "*", resolvedRecipe, capsWithSecrets, alias),
90
+ classifyExport(
91
+ api,
92
+ ep.subpath,
93
+ "*",
94
+ resolvedRecipe,
95
+ capsWithSecrets,
96
+ alias,
97
+ signals,
98
+ ),
83
99
  );
84
100
  }
85
101
  }
86
102
 
87
103
  if (api.entrypoints.length === 0) {
88
104
  perEntrypoint.push(
89
- classifyExport(api, ".", "*", resolvedRecipe, capsWithSecrets, alias),
105
+ classifyExport(
106
+ api,
107
+ ".",
108
+ "*",
109
+ resolvedRecipe,
110
+ capsWithSecrets,
111
+ alias,
112
+ signals,
113
+ ),
90
114
  );
91
115
  }
92
116
 
@@ -2,11 +2,12 @@ import type { SecretRequirement } from "../types/capability.ts";
2
2
  import type { IntegrationRecipe } from "../types/integration.ts";
3
3
  import type { PackageApi } from "../types/package-graph.ts";
4
4
  import { secret } from "../recipes/helpers.ts";
5
- import { gatherSignals } from "./signals.ts";
5
+ import { gatherSignals, type PackageSignals } from "./signals.ts";
6
6
 
7
7
  export function detectSecrets(
8
8
  api: PackageApi,
9
9
  recipe?: IntegrationRecipe,
10
+ precomputedSignals?: PackageSignals,
10
11
  ): SecretRequirement[] {
11
12
  const found = new Map<string, SecretRequirement>();
12
13
 
@@ -16,7 +17,7 @@ export function detectSecrets(
16
17
  }
17
18
  }
18
19
 
19
- const signals = gatherSignals(api);
20
+ const signals = precomputedSignals ?? gatherSignals(api);
20
21
  for (const evidence of signals.envSecretEvidence) {
21
22
  const envVar = evidence.replace(/^env:/, "");
22
23
  if (!found.has(envVar)) {