@akira-tl/forgerelay 0.8.7 → 0.8.9

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 (246) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +10 -18
  3. package/capabilities/host-integration/GUIDE.md +2 -2
  4. package/dist/activity/{audit-store.js → history/audit-store.js} +129 -21
  5. package/dist/activity/history/bash-output-store.js +250 -0
  6. package/dist/activity/{host-turn-store.js → history/host-turn-store.js} +4 -1
  7. package/dist/activity/{query-service.js → history/query-service.js} +13 -7
  8. package/dist/activity/{lifecycle.js → runtime/lifecycle.js} +1 -1
  9. package/dist/activity/{mcp-query-tools.js → runtime/mcp-query-tools.js} +3 -3
  10. package/dist/activity/storage/history.js +12 -0
  11. package/dist/activity/storage/paths.js +56 -0
  12. package/dist/activity/storage/segmented-log.js +149 -0
  13. package/dist/cli/setup-support.js +116 -0
  14. package/dist/cli.js +18 -126
  15. package/dist/lsp/code-intelligence.js +1 -1
  16. package/dist/lsp/test-support/server-fixture.js +9 -9
  17. package/dist/mcp/filesystem/filesystem-tools.js +245 -0
  18. package/dist/mcp/hooks/command-runner.js +79 -0
  19. package/dist/{hook-cli.js → mcp/hooks/hook-cli.js} +1 -1
  20. package/dist/{hooks.js → mcp/hooks/hooks.js} +3 -80
  21. package/dist/{oauth-provider.js → mcp/oauth/oauth-provider.js} +1 -1
  22. package/dist/{oauth-store.js → mcp/oauth/oauth-store.js} +5 -4
  23. package/dist/{operations → mcp/operations}/native-bulk-mutations.js +2 -2
  24. package/dist/mcp/panel/app.js +143 -0
  25. package/dist/{mcp-app-template.js → mcp/panel/mcp-app-template.js} +2 -38
  26. package/dist/mcp/process/runtime.js +257 -0
  27. package/dist/mcp/process/tools.js +346 -0
  28. package/dist/mcp/server/core/activity-support.js +70 -0
  29. package/dist/{capabilities.js → mcp/server/core/capabilities.js} +5 -3
  30. package/dist/{capability-registry.js → mcp/server/core/capability-registry.js} +2 -2
  31. package/dist/mcp/server/core/capability-support.js +90 -0
  32. package/dist/mcp/server/core/schemas.js +216 -0
  33. package/dist/mcp/server/core/tool-support.js +207 -0
  34. package/dist/mcp/server/core/version.js +9 -0
  35. package/dist/mcp/server/operations/runtime/filesystem-tools.js +400 -0
  36. package/dist/mcp/server/operations/runtime/operation-runtime.js +523 -0
  37. package/dist/mcp/server/transport/http-server.js +301 -0
  38. package/dist/mcp/server/transport/http-support.js +43 -0
  39. package/dist/mcp/server/workspace/runtime/workspace-open-presentation.js +222 -0
  40. package/dist/mcp/server/workspace/runtime/workspace-open-schema.js +187 -0
  41. package/dist/mcp/server/workspace/runtime/workspace-open.js +552 -0
  42. package/dist/mcp/server/workspace/runtime/workspace-tools.js +601 -0
  43. package/dist/{config.js → runtime/config/config.js} +3 -3
  44. package/dist/{user-config.js → runtime/config/user-config.js} +14 -54
  45. package/dist/{db → runtime/state/db}/client.js +1 -1
  46. package/dist/{db → runtime/state/db}/migrations.js +34 -3
  47. package/dist/runtime/state/lock/file-lock.js +130 -0
  48. package/dist/runtime/testing/server-fixture.js +190 -0
  49. package/dist/server.js +139 -4192
  50. package/dist/subagents/providers/adapters/claude.js +86 -52
  51. package/dist/subagents/providers/adapters/codex.js +103 -39
  52. package/dist/subagents/providers/adapters/opencode.js +114 -84
  53. package/dist/subagents/providers/adapters/pi.js +59 -8
  54. package/dist/subagents/providers/availability.js +15 -30
  55. package/dist/subagents/providers/runtime/external-command.js +56 -0
  56. package/dist/subagents/sessions/capability.js +1 -1
  57. package/dist/subagents/sessions/execution.js +1 -1
  58. package/dist/subagents/sessions/mcp/activity-audit-test-support.js +30 -0
  59. package/dist/subagents/sessions/store.js +1 -1
  60. package/dist/ui/.vite/manifest.json +342 -409
  61. package/dist/ui/activity-panel-app.html +2 -4
  62. package/dist/ui/assets/activity-panel-app-7Xe0alhm.css +1 -0
  63. package/dist/ui/assets/activity-panel-app-Sl1Jro8v.js +115 -0
  64. package/dist/ui/assets/angular-html-B_yn91wW.js +1 -0
  65. package/dist/ui/assets/{angular-ts-Bxh4-O1-.js → angular-ts-DSgtloKz.js} +1 -1
  66. package/dist/ui/assets/{apl-BmYHKQ6m.js → apl-NatWtF8X.js} +1 -1
  67. package/dist/ui/assets/{astro-C51vqDKq.js → astro-BYFEVBuN.js} +1 -1
  68. package/dist/ui/assets/{blade-CdhVsmwq.js → blade-DoO7yvMR.js} +1 -1
  69. package/dist/ui/assets/c-Rl2hMCcg.js +1 -0
  70. package/dist/ui/assets/{cobol-Cf6azoN_.js → cobol-ByC5mWiB.js} +1 -1
  71. package/dist/ui/assets/{coffee-vVdGzlmt.js → coffee-Dez77Qov.js} +1 -1
  72. package/dist/ui/assets/cpp-DtaAQT9h.js +1 -0
  73. package/dist/ui/assets/{crystal-5UZy6KIX.js → crystal-Bgmbf8ec.js} +1 -1
  74. package/dist/ui/assets/css-C1tjBtVN.js +1 -0
  75. package/dist/ui/assets/{edge-CESgo4ia.js → edge-DeH6u8Wg.js} +1 -1
  76. package/dist/ui/assets/{elixir-9FKfw4cJ.js → elixir-_H3KnmWT.js} +1 -1
  77. package/dist/ui/assets/{elm-Dv7A0aLa.js → elm-CsCe3U28.js} +1 -1
  78. package/dist/ui/assets/{erb-DHFmDvM0.js → erb-CbM-L2g8.js} +1 -1
  79. package/dist/ui/assets/{git-rebase-utbU6CzV.js → git-rebase-D0s5pDh9.js} +1 -1
  80. package/dist/ui/assets/{glimmer-js-t2kiCkyB.js → glimmer-js-BfOToq_A.js} +1 -1
  81. package/dist/ui/assets/{glimmer-ts-F0Jv5okV.js → glimmer-ts-CCUOkL2K.js} +1 -1
  82. package/dist/ui/assets/glsl-DH4ec9dE.js +1 -0
  83. package/dist/ui/assets/graphql-DilAMBoI.js +1 -0
  84. package/dist/ui/assets/{hack-8yjdbaSA.js → hack-BDkNDZlF.js} +1 -1
  85. package/dist/ui/assets/haml-D_QBp6K7.js +1 -0
  86. package/dist/ui/assets/{handlebars-BBFEg4Lo.js → handlebars-DePUrTpC.js} +1 -1
  87. package/dist/ui/assets/heavy-payload-DOwZpO6n.js +290 -0
  88. package/dist/ui/assets/html-By4dNnM4.js +1 -0
  89. package/dist/ui/assets/{html-derivative-DJAQcZyc.js → html-derivative-DDw9Ef4Q.js} +1 -1
  90. package/dist/ui/assets/{http-Dg5LSYRK.js → http-B0QxWc9M.js} +1 -1
  91. package/dist/ui/assets/{hurl-Y5uYzMZR.js → hurl-vMQ4lda1.js} +1 -1
  92. package/dist/ui/assets/java-DYRe2lWG.js +1 -0
  93. package/dist/ui/assets/javascript-CxyGqwcL.js +1 -0
  94. package/dist/ui/assets/{jinja-Bt30h8Ik.js → jinja-JUwV-fZt.js} +1 -1
  95. package/dist/ui/assets/{jison-D5uZ1Nyo.js → jison-7ZqCEvS8.js} +1 -1
  96. package/dist/ui/assets/json-dbltgiiA.js +1 -0
  97. package/dist/ui/assets/jsx-oDopT7YQ.js +1 -0
  98. package/dist/ui/assets/{julia-76hRaaGz.js → julia-CkKiNSav.js} +1 -1
  99. package/dist/ui/assets/{just-CDE7W0vW.js → just-DuqCAKJ3.js} +1 -1
  100. package/dist/ui/assets/{latex-CVO2Byab.js → latex-sudcRDSn.js} +1 -1
  101. package/dist/ui/assets/{liquid-CA-AS3EX.js → liquid-Di-08Js7.js} +1 -1
  102. package/dist/ui/assets/lua-YlqdMoV0.js +1 -0
  103. package/dist/ui/assets/{marko-_BWrPfny.js → marko-CJRNyJDb.js} +1 -1
  104. package/dist/ui/assets/{mdc-PyJv85eS.js → mdc-t12CzZHs.js} +1 -1
  105. package/dist/ui/assets/{nginx-DAWVw8yu.js → nginx-57-b4XwT.js} +1 -1
  106. package/dist/ui/assets/{nim-CKE1dzpU.js → nim-BzrswYQa.js} +1 -1
  107. package/dist/ui/assets/{perl-BBhWva19.js → perl-D9JR_iIh.js} +1 -1
  108. package/dist/ui/assets/{php-ChIeaAoF.js → php-Py2gFHil.js} +1 -1
  109. package/dist/ui/assets/{pug-CMgI5afi.js → pug-PzLLy0h1.js} +1 -1
  110. package/dist/ui/assets/{qml-CjxTkcFH.js → qml-By8fwgV4.js} +1 -1
  111. package/dist/ui/assets/r-CcezTbLq.js +1 -0
  112. package/dist/ui/assets/{razor-i4DbHr8p.js → razor-dG-vdhL_.js} +1 -1
  113. package/dist/ui/assets/regexp-BlsQ-N_8.js +1 -0
  114. package/dist/ui/assets/{rst-oy_97Kl4.js → rst-C2awDCat.js} +1 -1
  115. package/dist/ui/assets/{ruby-C5zYZIyl.js → ruby-zA2W_49d.js} +1 -1
  116. package/dist/ui/assets/{sas-BnMEh2S3.js → sas-D49bhyaN.js} +1 -1
  117. package/dist/ui/assets/scss-BQb-cp01.js +1 -0
  118. package/dist/ui/assets/shellscript-Dga4H_Ni.js +1 -0
  119. package/dist/ui/assets/{shellsession-BpE5o7_3.js → shellsession-n3-5CqcF.js} +1 -1
  120. package/dist/ui/assets/{soy-COesmhTY.js → soy-XYBOf_BA.js} +1 -1
  121. package/dist/ui/assets/sql-ET4u5Cpl.js +1 -0
  122. package/dist/ui/assets/{stata-CGQEuSZq.js → stata-CLHcJHO_.js} +1 -1
  123. package/dist/ui/assets/{surrealql-Bz4JbU-9.js → surrealql-BdjQ60T4.js} +1 -1
  124. package/dist/ui/assets/{svelte-1jM2ejXj.js → svelte-B2RPtKJe.js} +1 -1
  125. package/dist/ui/assets/{templ-C-VwELcp.js → templ-CrByPW_W.js} +1 -1
  126. package/dist/ui/assets/{tex-t1rUiQCm.js → tex-DZBkg363.js} +1 -1
  127. package/dist/ui/assets/{ts-tags-Bewoa6pS.js → ts-tags-DJR3Gphb.js} +1 -1
  128. package/dist/ui/assets/tsx-CajzROyy.js +1 -0
  129. package/dist/ui/assets/{twig-DVg-vELl.js → twig-BZjk5Zda.js} +1 -1
  130. package/dist/ui/assets/typescript-B-EWToLj.js +1 -0
  131. package/dist/ui/assets/{vue-wPQ7UlMy.js → vue-D_rHCCr8.js} +1 -1
  132. package/dist/ui/assets/{vue-html-BHtJ8geX.js → vue-html-CC4WlvVt.js} +1 -1
  133. package/dist/ui/assets/{vue-vine-CNSGAWwc.js → vue-vine-BgNMVgpk.js} +1 -1
  134. package/dist/ui/assets/xml-BI86-WbH.js +1 -0
  135. package/dist/ui/assets/{xsl-3_vJ27aE.js → xsl-DXeLZV4J.js} +1 -1
  136. package/dist/ui/assets/yaml-60_PFlWa.js +1 -0
  137. package/dist/workspaces/bootstrap.js +72 -0
  138. package/dist/workspaces/context.js +302 -0
  139. package/dist/workspaces/conversation-test-support.js +86 -0
  140. package/dist/{git-worktrees.js → workspaces/git/git-worktrees.js} +1 -1
  141. package/dist/workspaces/inventory.js +131 -0
  142. package/dist/workspaces/paths.js +55 -0
  143. package/dist/{remote-auth.js → workspaces/relay/auth/remote-auth.js} +2 -2
  144. package/dist/workspaces/relay/result-support.js +111 -0
  145. package/dist/workspaces/relay/tests/test-support.js +203 -0
  146. package/dist/{remote-mcp-connection-pool.js → workspaces/relay/transport/remote-mcp-connection-pool.js} +1 -1
  147. package/dist/workspaces/relay/types.js +1 -0
  148. package/dist/{remote-workspace-relay.js → workspaces/relay/workspace-relay.js} +23 -172
  149. package/dist/workspaces/resources/skills.js +285 -0
  150. package/dist/{review-checkpoints.js → workspaces/review/review-checkpoints.js} +2 -2
  151. package/dist/workspaces/sessions.js +457 -0
  152. package/dist/{workspace-store.js → workspaces/state/workspace-store.js} +2 -2
  153. package/dist/workspaces.js +69 -991
  154. package/docs/chatgpt-coding-workflow.md +3 -11
  155. package/docs/configuration.md +12 -25
  156. package/docs/gotchas.md +0 -30
  157. package/docs/roadmap.md +6 -10
  158. package/docs/security.md +1 -5
  159. package/docs/setup.md +0 -11
  160. package/package.json +6 -8
  161. package/scripts/ci/architecture.mjs +109 -0
  162. package/scripts/ci/verify.mjs +5 -0
  163. package/scripts/debug/accept/bootstrap.mjs +326 -0
  164. package/scripts/debug/accept/harness.mjs +76 -0
  165. package/scripts/debug/accept/support.mjs +432 -0
  166. package/scripts/debug/accept.mjs +43 -806
  167. package/scripts/debug/relay-accept/support.mjs +135 -0
  168. package/scripts/debug/relay-accept.mjs +26 -115
  169. package/scripts/debug/traffic/support.mjs +167 -0
  170. package/scripts/debug/traffic/traffic-audit.mjs +4 -161
  171. package/scripts/{lsp-interop-support.test.mjs → lsp/interop-support.test.mjs} +1 -1
  172. package/scripts/{lsp-interop.mjs → lsp/interop.mjs} +3 -3
  173. package/scripts/wiki/sync.mjs +21 -10
  174. package/dist/activity/bash-output-store.js +0 -127
  175. package/dist/pi-tools.js +0 -110
  176. package/dist/skills.js +0 -127
  177. package/dist/ui/assets/activity-panel-app-CUAN6zyW.js +0 -2
  178. package/dist/ui/assets/angular-html-BkgDQl-G.js +0 -1
  179. package/dist/ui/assets/c-IBzBpxAO.js +0 -1
  180. package/dist/ui/assets/chunk-EyZ2wyi3.js +0 -1
  181. package/dist/ui/assets/cpp-CVHeO-Jk.js +0 -1
  182. package/dist/ui/assets/css-DEfus9J5.js +0 -1
  183. package/dist/ui/assets/glsl-_ooCjaeB.js +0 -1
  184. package/dist/ui/assets/graphql-B9LqP-cY.js +0 -1
  185. package/dist/ui/assets/haml-BU5EoZBn.js +0 -1
  186. package/dist/ui/assets/heavy-payload-CgzrutLm.js +0 -4
  187. package/dist/ui/assets/html-D-C6YZk4.js +0 -1
  188. package/dist/ui/assets/java-ppHvycj5.js +0 -1
  189. package/dist/ui/assets/javascript-DDTjKLlQ.js +0 -1
  190. package/dist/ui/assets/json-Cw91r8h1.js +0 -1
  191. package/dist/ui/assets/jsx-04X2FT_1.js +0 -1
  192. package/dist/ui/assets/lua-CiyBp52Y.js +0 -1
  193. package/dist/ui/assets/r-DfFga4si.js +0 -1
  194. package/dist/ui/assets/regexp-iC9_nbSI.js +0 -1
  195. package/dist/ui/assets/review-payload-BrLbezbq.js +0 -1
  196. package/dist/ui/assets/scrollbar-CbhpdW05.js +0 -287
  197. package/dist/ui/assets/scss-BfZXsAWQ.js +0 -1
  198. package/dist/ui/assets/shellscript-BC2srNaB.js +0 -1
  199. package/dist/ui/assets/sql-Ccv_yeUm.js +0 -1
  200. package/dist/ui/assets/tsx-CTXzrBkN.js +0 -1
  201. package/dist/ui/assets/typescript--ElHoFkw.js +0 -1
  202. package/dist/ui/assets/workspace-app-Bhj96tsR.js +0 -1
  203. package/dist/ui/assets/workspace-app-CxwJuZyS.js +0 -111
  204. package/dist/ui/assets/workspace-app-D6UR0AFl.js +0 -5
  205. package/dist/ui/assets/workspace-app-ldjBmCJR.css +0 -1
  206. package/dist/ui/assets/workspace-lifecycle-app-Cqfhx9pV.js +0 -1
  207. package/dist/ui/assets/xml-JnmX6vyS.js +0 -1
  208. package/dist/ui/assets/yaml-OAcZkP-w.js +0 -1
  209. package/dist/ui/workspace-app.html +0 -18
  210. package/dist/ui/workspace-lifecycle-app.html +0 -18
  211. package/docs/agent-profile-schema.md +0 -114
  212. package/docs/artifact-exchange.md +0 -65
  213. package/docs/versioning.md +0 -205
  214. /package/capabilities/{managed-worktrees → workspace/managed-worktrees}/GUIDE.md +0 -0
  215. /package/capabilities/{workspace-tasks → workspace/workspace-tasks}/GUIDE.md +0 -0
  216. /package/dist/activity/{process-output-audit.js → runtime/process-output-audit.js} +0 -0
  217. /package/dist/{artifact-error.js → mcp/artifacts/artifact-error.js} +0 -0
  218. /package/dist/{artifact-tools.js → mcp/artifacts/artifact-tools.js} +0 -0
  219. /package/dist/{incoming-artifacts.js → mcp/artifacts/incoming-artifacts.js} +0 -0
  220. /package/dist/{advertised-files.js → mcp/filesystem/advertised-files.js} +0 -0
  221. /package/dist/{apply-patch.js → mcp/filesystem/apply-patch.js} +0 -0
  222. /package/dist/{file-mutations.js → mcp/filesystem/file-mutations.js} +0 -0
  223. /package/dist/{roots.js → mcp/filesystem/roots.js} +0 -0
  224. /package/dist/{oauth → mcp/oauth}/public-url.js +0 -0
  225. /package/dist/{oauth → mcp/oauth}/router.js +0 -0
  226. /package/dist/{operations → mcp/operations}/batch/executor.js +0 -0
  227. /package/dist/{operations → mcp/operations}/batch/scheduler.js +0 -0
  228. /package/dist/{operations → mcp/operations}/batch/types.js +0 -0
  229. /package/dist/{operations → mcp/operations}/bulk-mutation.js +0 -0
  230. /package/dist/{operations → mcp/operations}/bulk-read.js +0 -0
  231. /package/dist/{operations → mcp/operations}/core-operation-executor.js +0 -0
  232. /package/dist/{process-platform.js → mcp/process/process-platform.js} +0 -0
  233. /package/dist/{process-sessions.js → mcp/process/process-sessions.js} +0 -0
  234. /package/dist/{request-meta.js → mcp/request-meta.js} +0 -0
  235. /package/dist/{mcp-sessions.js → mcp/server/transport/mcp-sessions.js} +0 -0
  236. /package/dist/{server-shutdown.js → mcp/server/transport/server-shutdown.js} +0 -0
  237. /package/dist/{logger.js → runtime/logging/logger.js} +0 -0
  238. /package/dist/{db → runtime/state/db}/schema.js +0 -0
  239. /package/dist/{composite-activity.js → workspaces/composite/composite-activity.js} +0 -0
  240. /package/dist/{composite-workspaces.js → workspaces/composite/composite-workspaces.js} +0 -0
  241. /package/dist/{git.js → workspaces/git/git.js} +0 -0
  242. /package/dist/{workspace-presentation.js → workspaces/presentation/workspace-presentation.js} +0 -0
  243. /package/dist/{remote-transport.js → workspaces/relay/transport/remote-transport.js} +0 -0
  244. /package/dist/{workspace-task-reminders.js → workspaces/tasks/workspace-task-reminders.js} +0 -0
  245. /package/dist/{workspace-tasks.js → workspaces/tasks/workspace-tasks.js} +0 -0
  246. /package/scripts/{lsp-interop-support.mjs → lsp/interop-support.mjs} +0 -0
@@ -164,9 +164,6 @@ same safe finalize/integrate/cleanup lifecycle before ForgeRelay deletes its ide
164
164
  For an already-closed managed-worktree Workspace, delete removes only ForgeRelay-owned
165
165
  state and does not recreate the physical backing.
166
166
 
167
- Legacy `devspace/*` managed branches remain closable when they are already stored
168
- in workspace metadata; only new managed branches use `forgerelay/*`.
169
-
170
167
  ## Instructions
171
168
 
172
169
  When a workspace opens, ForgeRelay first loads exactly one global system-instructions
@@ -253,8 +250,6 @@ global config directory plus:
253
250
  .forgerelay/agents/*.md
254
251
  ```
255
252
 
256
- Rename-era `.devspace/agents` discovery has ended.
257
-
258
253
  The workspace result exposes only compact profile metadata so the host can
259
254
  choose a provider/profile without loading full provider launch details. Read the
260
255
  ForgeRelay-owned `subagents` capability guide when delegation is actually needed;
@@ -350,10 +345,7 @@ and keeps widget usage focused on workspace/change review.
350
345
 
351
346
  `FORGERELAY_WIDGETS=off` disables widget UI.
352
347
 
353
- ## Legacy configuration
348
+ ## Configuration
354
349
 
355
- `FORGERELAY_*` is the canonical environment-variable prefix. Rename-era
356
- `DEVSPACE_*` fallbacks and automatic `~/.devspace` reuse have ended. Migrate
357
- older installations explicitly; persisted internal identifiers that would
358
- otherwise orphan state remain compatible. See
359
- [Configuration Reference](configuration.md) for the current rules.
350
+ `FORGERELAY_*` is the canonical environment-variable prefix. See
351
+ [Configuration Reference](configuration.md) for the current settings.
@@ -18,11 +18,6 @@ Override the directory with:
18
18
  FORGERELAY_CONFIG_DIR=/path/to/config npx @akira-tl/forgerelay serve
19
19
  ```
20
20
 
21
- The rename-era automatic fallback has ended. `DEVSPACE_CONFIG_DIR` is ignored,
22
- and the default directory is always `~/.forgerelay`. If an older installation
23
- still has data in a DevSpace-named directory, migrate it explicitly or point
24
- `FORGERELAY_CONFIG_DIR` at that directory during the migration.
25
-
26
21
  ## Commands
27
22
 
28
23
  ```bash
@@ -35,9 +30,7 @@ npx @akira-tl/forgerelay config set publicBaseUrl https://forge.example.com/forg
35
30
 
36
31
  ## Environment variables
37
32
 
38
- The public prefix is `FORGERELAY_*`. Rename-era `DEVSPACE_*` environment
39
- variables are no longer read. Migrate automation, service files, shell profiles,
40
- and CI configuration to the canonical ForgeRelay names.
33
+ The public environment-variable prefix is `FORGERELAY_*`.
41
34
 
42
35
  ## Core variables
43
36
 
@@ -79,11 +72,6 @@ A single persisted string remains fully supported, so existing configs require n
79
72
  migration. For environment configuration, use a comma-separated list in
80
73
  `FORGERELAY_PUBLIC_BASE_URL`.
81
74
 
82
- ForgeRelay no longer auto-detects DevSpace-named state or worktree directories.
83
- Persisted `stateDir` and `worktreeRoot` values in `config.json` continue to win
84
- over defaults, so an explicit configuration may temporarily point at an older
85
- location while data is migrated.
86
-
87
75
  ## Native artifact download
88
76
 
89
77
  Native-file download is disabled by default. Enable it with:
@@ -101,7 +89,7 @@ The same settings may be persisted as `artifactsEnabled` and
101
89
  `artifactMaxFileBytes` in `config.json`.
102
90
 
103
91
  The tool currently supports the secure native-file publication path on Linux.
104
- See [Native File Download](artifact-exchange.md).
92
+ See [Native File Download](reference/artifact-exchange.md).
105
93
 
106
94
  ## OAuth
107
95
 
@@ -111,13 +99,9 @@ ForgeRelay uses a single-user Owner-password OAuth approval flow.
111
99
  | --- | --- |
112
100
  | `FORGERELAY_OAUTH_ACCESS_TOKEN_TTL_SECONDS` | `3600` |
113
101
  | `FORGERELAY_OAUTH_REFRESH_TOKEN_TTL_SECONDS` | `2592000` |
114
- | `FORGERELAY_OAUTH_SCOPES` | legacy-compatible internal scope `devspace` |
102
+ | `FORGERELAY_OAUTH_SCOPES` | `forgerelay` |
115
103
  | `FORGERELAY_OAUTH_ALLOWED_REDIRECT_HOSTS` | `chatgpt.com,localhost,127.0.0.1` |
116
104
 
117
- The default OAuth scope intentionally remains the legacy internal value during
118
- the rename so existing registrations/state do not need a destructive migration.
119
- This is a protocol compatibility identifier, not product branding.
120
-
121
105
  MCP clients discover metadata from:
122
106
 
123
107
  ```text
@@ -136,7 +120,7 @@ MCP clients discover metadata from:
136
120
  | `codex` | Experimental Codex-shaped compatibility adapter using `open_workspace`, `close_workspace`, `read`, `rename`, `delete`, `apply_patch`, `exec_command`, `write_stdin`, and `capability`. It does not define the ForgeRelay canonical interface. |
137
121
 
138
122
  `FORGERELAY_MINIMAL_TOOLS` remains a compatibility-style boolean alias when the
139
- explicit tool mode is unset. DevSpace-prefixed equivalents are no longer read.
123
+ explicit tool mode is unset.
140
124
 
141
125
  `minimal` and `full` now resolve to the same regular 9-tool `tools/list`; `full`
142
126
  is retained only as a configuration-compatibility value. `codex` selects a
@@ -581,7 +565,7 @@ directories; deeper instruction files are discovered lazily when a workspace pat
581
565
  is first accessed. Reads surface newly discovered instructions inline, while
582
566
  side-effecting file/shell operations stop before execution and require a retry if
583
567
  that access discovers new local instructions. `FORGERELAY_AGENT_DIR` does not
584
- select a global instruction file; it remains a compatibility path for Agent Skills.
568
+ select a global instruction file; its `skills` child is an additional Agent Skills source.
585
569
 
586
570
  ## Skills and subagents
587
571
 
@@ -589,7 +573,7 @@ select a global instruction file; it remains a compatibility path for Agent Skil
589
573
  | --- | --- |
590
574
  | `FORGERELAY_SKILLS` | Set to `0` to hide skills. Enabled by default. |
591
575
  | `FORGERELAY_SUBAGENTS` | Set to `1` to expose configured subagent profiles. |
592
- | `FORGERELAY_AGENT_DIR` | Defaults to `~/.codex`; its `skills` child is loaded for compatibility. |
576
+ | `FORGERELAY_AGENT_DIR` | Defaults to `~/.codex`; its `skills` child is included as an additional Skill source. |
593
577
  | `FORGERELAY_SKILL_PATHS` | Optional comma-separated additional skill directories. |
594
578
 
595
579
  Standard Agent Skills are discovered from:
@@ -605,9 +589,12 @@ When subagents are enabled, profiles are discovered from:
605
589
  - the active ForgeRelay config directory's `agents/*.md`;
606
590
  - project `.forgerelay/agents/*.md`.
607
591
 
608
- DevSpace-named profile directories are no longer discovered automatically. Move
609
- those profiles or explicitly select their parent with `FORGERELAY_CONFIG_DIR`
610
- during migration.
592
+
593
+ ForgeRelay does not install or bundle coding-agent executors. Subagent providers
594
+ are available only when the corresponding user-installed executable can be found
595
+ on the server. The default commands are `codex`, `claude`, `opencode`, `pi`,
596
+ `cursor-agent`, and `copilot`. Override the first four when needed with
597
+ `CODEX_COMMAND`, `CLAUDE_COMMAND`, `OPENCODE_COMMAND`, or `PI_COMMAND`.
611
598
 
612
599
  The ForgeRelay-owned `subagents` capability guide teaches the current CLI
613
600
  workflow on demand:
package/docs/gotchas.md CHANGED
@@ -28,27 +28,6 @@ npm rebuild better-sqlite3
28
28
  npx @akira-tl/forgerelay doctor
29
29
  ```
30
30
 
31
- ## Existing DevSpace config stopped being used
32
-
33
- The automatic rename-era fallback has ended. ForgeRelay now defaults to
34
- `~/.forgerelay` and ignores `DEVSPACE_*` environment variables.
35
-
36
- Check the resolved directory:
37
-
38
- ```bash
39
- forgerelay doctor
40
- ```
41
-
42
- If an older installation still needs data from a DevSpace-named directory,
43
- point the canonical setting at it explicitly while migrating:
44
-
45
- ```bash
46
- FORGERELAY_CONFIG_DIR="$HOME/.forgerelay" forgerelay init
47
- ```
48
-
49
- Do not delete the old directory until you have confirmed which persisted state,
50
- worktrees, skills, and profiles you still need.
51
-
52
31
  ## Public base URL includes `/mcp`
53
32
 
54
33
  Store the public base URL *before* the final `/mcp`. A routed deployment keeps
@@ -135,10 +114,6 @@ New installs normally use:
135
114
  ~/.forgerelay/auth.json
136
115
  ```
137
116
 
138
- ForgeRelay no longer discovers `~/.devspace/auth.json` automatically. Move the
139
- credential file to the active ForgeRelay config directory or explicitly set
140
- `FORGERELAY_CONFIG_DIR` while migrating.
141
-
142
117
  Regenerate setup intentionally with:
143
118
 
144
119
  ```bash
@@ -168,8 +143,6 @@ New managed branches use:
168
143
  forgerelay/*
169
144
  ```
170
145
 
171
- Legacy persisted `devspace/*` branches remain valid and closable.
172
-
173
146
  Uncommitted source-checkout changes are not automatically copied into a newly
174
147
  created worktree.
175
148
 
@@ -229,9 +202,6 @@ New profile locations include:
229
202
  .forgerelay/agents/*.md
230
203
  ```
231
204
 
232
- Legacy `.devspace/agents` paths are no longer scanned automatically. Move
233
- profiles into one of the canonical locations before upgrading.
234
-
235
205
  `forgerelay agents ls` lists sessions, not profile definitions. The compact
236
206
  profile catalog is returned through `open_workspace`.
237
207
 
package/docs/roadmap.md CHANGED
@@ -55,8 +55,7 @@ The initial independent release establishes:
55
55
  - branch-backed managed worktrees using `forgerelay/*` branches;
56
56
  - safe `close_worktree` fast-forward lifecycle;
57
57
  - persisted worktree branch/target metadata;
58
- - existing local coding-agent profile/provider integration;
59
- - compatibility with legacy DevSpace configuration/state identifiers.
58
+ - existing local coding-agent profile/provider integration.
60
59
 
61
60
  ## 0.2 — Hooks v1
62
61
 
@@ -358,9 +357,10 @@ Task is a checklist/continuation primitive rather than an execution scheduler:
358
357
  Subagent coordination can reference Task content when useful, but ForgeRelay does
359
358
  not bind Tasks to Subagent Sessions or infer Task completion from execution facts.
360
359
 
361
- ## Compatibility policy
360
+ ## Project identity
362
361
 
363
- New public names use ForgeRelay:
362
+ ForgeRelay uses its own package, CLI, configuration, state, project-directory,
363
+ and managed-branch namespaces:
364
364
 
365
365
  - `@akira-tl/forgerelay`
366
366
  - `forgerelay`
@@ -369,9 +369,5 @@ New public names use ForgeRelay:
369
369
  - `.forgerelay`
370
370
  - `forgerelay/*` managed branches
371
371
 
372
- Rename-era public compatibility adapters have a bounded migration window rather
373
- than permanent support. `DEVSPACE_*`, automatic `~/.devspace` reuse, legacy
374
- `.devspace/agents` discovery, and old package-path special cases are retired once
375
- they are outside that window. Persisted internal identifiers remain compatible
376
- when removing them would orphan real user state; those are storage/protocol
377
- migration concerns, not public product aliases.
372
+ Upstream attribution is preserved separately through `LICENSE`, `NOTICE.md`, and
373
+ release provenance checks; it is not a runtime compatibility surface.
package/docs/security.md CHANGED
@@ -60,10 +60,6 @@ FORGERELAY_OAUTH_OWNER_TOKEN="$(openssl rand -base64 32)"
60
60
 
61
61
  The token must be at least 16 characters.
62
62
 
63
- Rename-era `DEVSPACE_*` environment-variable and automatic `~/.devspace`
64
- configuration fallbacks have ended. Use canonical `FORGERELAY_*` settings and
65
- explicit paths when migrating older installations.
66
-
67
63
  ## Public URL and tunnels
68
64
 
69
65
  ForgeRelay needs `FORGERELAY_PUBLIC_BASE_URL` when an MCP client reaches it
@@ -186,7 +182,7 @@ not accept arbitrary signed URLs, local paths,
186
182
  embedded credentials, or base64 strings as substitutes.
187
183
 
188
184
  Downloads are streamed, size-limited, created without overwrite, and published
189
- as owner-only files. See [Native File Download](artifact-exchange.md).
185
+ as owner-only files. See [Native File Download](reference/artifact-exchange.md).
190
186
 
191
187
  ## Logging
192
188
 
package/docs/setup.md CHANGED
@@ -119,17 +119,6 @@ New installations use:
119
119
 
120
120
  Keep `auth.json` private.
121
121
 
122
- ### Existing DevSpace configuration
123
-
124
- Automatic DevSpace directory fallback has ended. ForgeRelay defaults to
125
- `~/.forgerelay` and ignores `DEVSPACE_CONFIG_DIR`.
126
-
127
- Before upgrading an older installation, move or copy the needed configuration
128
- and credentials into the ForgeRelay directory, or temporarily point
129
- `FORGERELAY_CONFIG_DIR` at the old directory. If state or managed worktrees live
130
- under older paths, preserve them with explicit `stateDir` / `worktreeRoot`
131
- configuration until migration is complete.
132
-
133
122
  ## Check the setup
134
123
 
135
124
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akira-tl/forgerelay",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
4
4
  "description": "Local development control plane for MCP coding agents.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Akira-TL/forgerelay#readme",
@@ -41,9 +41,11 @@
41
41
  "debug:serve": "node scripts/debug/serve.mjs",
42
42
  "debug:accept": "node scripts/debug/accept.mjs",
43
43
  "debug:accept:relay": "node scripts/debug/relay-accept.mjs",
44
- "lsp:interop": "node scripts/lsp-interop.mjs",
44
+ "traffic:audit": "node --import tsx scripts/debug/traffic/traffic-audit.mjs",
45
+ "lsp:interop": "node scripts/lsp/interop.mjs",
45
46
  "wiki:check": "node scripts/wiki/sync.mjs check",
46
47
  "wiki:publish": "node scripts/wiki/sync.mjs publish",
48
+ "architecture:check": "node scripts/ci/architecture.mjs",
47
49
  "ci:verify": "node scripts/ci/verify.mjs",
48
50
  "release:parity": "node scripts/release-parity.mjs",
49
51
  "release:pack": "node scripts/release/pack.mjs",
@@ -51,7 +53,7 @@
51
53
  "release:push-ready": "node scripts/release/push-ready.mjs",
52
54
  "postinstall": "node scripts/fix-node-pty-permissions.mjs",
53
55
  "start": "node dist/cli.js serve",
54
- "test": "node --test scripts/debug/runtime.test.mjs scripts/release-proof.test.mjs scripts/release/release-gate.test.mjs scripts/release/push-ready.test.mjs scripts/release/release-version.test.mjs && tsx src/oauth/router.test.ts && tsx src/remote-auth-cli.test.ts && tsx src/remote-ssh-auth-cli.test.ts && tsx src/remote-workspace-relay.test.ts && tsx src/remote-workspace-relay-process.test.ts && tsx src/config.test.ts && tsx src/lsp/language-server-config.test.ts && tsx src/lsp/normalization/hover.test.ts && tsx src/lsp/references.server.test.ts && tsx src/lsp/operations/document-symbols.server.test.ts && tsx src/lsp/operations/workspace-symbols.server.test.ts && tsx src/lsp/operations/diagnostics-push.server.test.ts && tsx src/lsp/operations/diagnostics-pull.server.test.ts && tsx src/lsp/operations/request-hardening.server.test.ts && tsx src/lsp/operations/recovery.server.test.ts && tsx src/lsp/operations/lifecycle.server.test.ts && tsx src/lsp/runtime/semantic-requests.test.ts && tsx src/logger.test.ts && tsx src/proxy-trust.test.ts && tsx src/mcp-app-template.test.ts && tsx src/hooks.test.ts && tsx src/capability-registry.test.ts && tsx src/mcp/server-instructions.test.ts && tsx src/request-meta.test.ts && tsx src/incoming-artifacts.test.ts && tsx src/artifact-download.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/workspace-lifecycle-app.test.ts && tsx src/ui/activity/model.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/subagents/providers/adapters/codex.test.ts && tsx src/subagents/providers/registry.test.ts && tsx src/subagents/providers/availability.test.ts && tsx src/subagents/profiles.test.ts && tsx src/subagents/cli-target.test.ts && tsx src/subagents/sessions/store.test.ts && tsx src/subagents/sessions/manager.test.ts && tsx src/subagents/sessions/mcp/capability.server.test.ts && tsx src/subagents/sessions/mcp/continuation.server.test.ts && tsx src/subagents/sessions/mcp/lifecycle.server.test.ts && tsx src/subagents/sessions/mcp/reconciliation.server.test.ts && tsx src/subagents/sessions/mcp/routing.server.test.ts && tsx src/roots.test.ts && tsx src/file-mutations.test.ts && tsx src/operations/edit-preflight.test.ts && tsx src/skills.test.ts && tsx src/db/migrations.test.ts && tsx src/workspace-store.test.ts && tsx src/workspace-tasks.test.ts && tsx src/workspace-task-reminders.test.ts && tsx src/activity/audit-store.test.ts && tsx src/activity/bash-output-store.test.ts && tsx src/activity/lifecycle.test.ts && tsx src/activity/query-service.test.ts && tsx src/operations/core-operation-executor.test.ts && tsx src/operations/bulk-mutation.test.ts && tsx src/operations/batch/scheduler.test.ts && tsx src/operations/batch/executor-policy.test.ts && tsx src/workspaces.test.ts && tsx src/workspace-conversation.test.ts && tsx src/review-checkpoints.test.ts && tsx src/lsp/code-intelligence.server.test.ts && npm run build:app && tsx src/server.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts",
56
+ "test": "node --test scripts/debug/runtime.test.mjs scripts/release-proof.test.mjs scripts/release/release-gate.test.mjs scripts/release/push-ready.test.mjs scripts/release/release-version.test.mjs && tsx src/mcp/oauth/router.test.ts && tsx src/workspaces/relay/auth/remote-auth-cli.test.ts && tsx src/workspaces/relay/auth/remote-ssh-auth-cli.test.ts && tsx src/workspaces/relay/tests/lifecycle.test.ts && tsx src/workspaces/relay/tests/routing.test.ts && tsx src/workspaces/relay/tests/ssh.test.ts && tsx src/workspaces/relay/tests/process.test.ts && tsx src/runtime/config/config.test.ts && tsx src/lsp/language-server-config.test.ts && tsx src/lsp/normalization/hover.test.ts && tsx src/lsp/references.server.test.ts && tsx src/lsp/operations/document-symbols.server.test.ts && tsx src/lsp/operations/workspace-symbols.server.test.ts && tsx src/lsp/operations/diagnostics-push.server.test.ts && tsx src/lsp/operations/diagnostics-pull.server.test.ts && tsx src/lsp/operations/request-hardening.server.test.ts && tsx src/lsp/operations/recovery.server.test.ts && tsx src/lsp/operations/lifecycle.server.test.ts && tsx src/lsp/runtime/semantic-requests.test.ts && tsx src/runtime/logging/logger.test.ts && tsx src/runtime/logging/proxy-trust.test.ts && tsx src/runtime/state/lock/file-lock.test.ts && tsx src/mcp/panel/mcp-app-template.test.ts && tsx src/mcp/hooks/hooks.test.ts && tsx src/mcp/server/core/capability-registry.test.ts && tsx src/mcp/server-instructions.test.ts && tsx src/mcp/request-meta.test.ts && tsx src/mcp/artifacts/incoming-artifacts.test.ts && tsx src/mcp/artifacts/artifact-download.test.ts && tsx src/ui/core/card-types.test.ts && tsx src/ui/activity/model.test.ts && tsx src/ui/activity/detail-card.test.ts && tsx src/ui/review/patch-display.test.ts && tsx src/ui/core/tool-display.test.ts && tsx src/mcp/filesystem/apply-patch.test.ts && tsx src/mcp/process/process-platform.test.ts && tsx src/mcp/process/process-sessions.test.ts && tsx src/mcp/server/transport/mcp-sessions.test.ts && tsx src/mcp/server/transport/server-shutdown.test.ts && tsx src/subagents/providers/adapters/codex.test.ts && tsx src/subagents/providers/adapters/pi.test.ts && tsx src/subagents/providers/registry.test.ts && tsx src/subagents/providers/availability.test.ts && tsx src/subagents/profiles.test.ts && tsx src/subagents/cli-target.test.ts && tsx src/subagents/sessions/store.test.ts && tsx src/subagents/sessions/manager.test.ts && tsx src/subagents/sessions/mcp/capability.server.test.ts && tsx src/subagents/sessions/mcp/continuation.server.test.ts && tsx src/subagents/sessions/mcp/lifecycle.server.test.ts && tsx src/subagents/sessions/mcp/reconciliation.server.test.ts && tsx src/subagents/sessions/mcp/routing.server.test.ts && tsx src/mcp/filesystem/roots.test.ts && tsx src/mcp/filesystem/file-mutations.test.ts && tsx src/mcp/operations/edit-preflight.test.ts && tsx src/workspaces/resources/skills.test.ts && tsx src/runtime/state/db/migrations.test.ts && tsx src/workspaces/state/workspace-store.test.ts && tsx src/workspaces/tasks/workspace-tasks.test.ts && tsx src/workspaces/tasks/workspace-task-reminders.test.ts && tsx src/activity/history/audit-store.test.ts && tsx src/activity/history/bash-output-store.test.ts && tsx src/activity/runtime/lifecycle.test.ts && tsx src/activity/history/query-service.test.ts && tsx src/mcp/operations/core-operation-executor.test.ts && tsx src/mcp/operations/bulk-mutation.test.ts && tsx src/mcp/operations/batch/scheduler.test.ts && tsx src/mcp/operations/batch/executor-policy.test.ts && tsx src/workspaces.test.ts && tsx src/workspaces/conversation-checkout.test.ts && tsx src/workspaces/conversation-worktree.test.ts && tsx src/workspaces/review/review-checkpoints.test.ts && tsx src/lsp/code-intelligence.server.test.ts && npm run build:app && tsx src/mcp/process/server.test.ts && tsx src/mcp/panel/server.test.ts && tsx src/mcp/server/server.test.ts && tsx src/mcp/oauth/oauth-store.test.ts && tsx src/cli/cli.test.ts",
55
57
  "typecheck": "tsc -p tsconfig.json --noEmit",
56
58
  "release:check": "node scripts/release-version.mjs check",
57
59
  "release:tag-check": "node scripts/release-version.mjs tag",
@@ -73,15 +75,11 @@
73
75
  "license": "MIT",
74
76
  "dependencies": {
75
77
  "@agentclientprotocol/sdk": "^1.1.0",
76
- "@anthropic-ai/claude-agent-sdk": "^0.3.200",
77
78
  "@clack/prompts": "^1.5.1",
78
- "@earendil-works/pi-coding-agent": "^0.80.3",
79
79
  "@modelcontextprotocol/ext-apps": "^1.7.2",
80
80
  "@modelcontextprotocol/sdk": "^1.29.0",
81
- "@openai/codex-sdk": "^0.142.5",
82
- "@opencode-ai/sdk": "^1.17.13",
83
81
  "@pierre/diffs": "^1.2.5",
84
- "better-sqlite3": "^12.10.0",
82
+ "better-sqlite3": "^13.0.3",
85
83
  "diff": "^8.0.3",
86
84
  "drizzle-orm": "^0.45.2",
87
85
  "express": "^5.2.1",
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import { extname, basename, dirname } from "node:path";
5
+ import { readFileSync } from "node:fs";
6
+
7
+ const MAX_LINES = 800;
8
+ const MAX_DIRECT_FILES = 8;
9
+ const MAX_DIRECT_DIRS = 8;
10
+ const LINE_LIMIT_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".mjs", ".cjs", ".css"]);
11
+
12
+ // Repository-root protocol files are intentionally discoverable by Git, npm,
13
+ // Node, Vite, contributors, and agents. Keep that conventional surface explicit
14
+ // instead of hiding required/default-discovery files merely to satisfy a count.
15
+ const ROOT_PROTOCOL_FILES = new Set([
16
+ ".env.example",
17
+ ".gitignore",
18
+ ".nvmrc",
19
+ "AGENTS.md",
20
+ "CHANGELOG.md",
21
+ "CONTEXT.md",
22
+ "CONTRIBUTING.md",
23
+ "LICENSE",
24
+ "NOTICE.md",
25
+ "README.md",
26
+ "package-lock.json",
27
+ "package.json",
28
+ "tsconfig.build.json",
29
+ "tsconfig.json",
30
+ "vite.config.ts",
31
+ ]);
32
+
33
+ const tracked = gitTrackedFiles();
34
+ const violations = [];
35
+ const directFiles = new Map();
36
+ const directDirs = new Map();
37
+
38
+ for (const path of tracked) {
39
+ const parent = normalizeDirectory(dirname(path));
40
+ directFiles.set(parent, (directFiles.get(parent) ?? 0) + 1);
41
+
42
+ let child = parent;
43
+ while (child !== ".") {
44
+ const grandparent = normalizeDirectory(dirname(child));
45
+ let children = directDirs.get(grandparent);
46
+ if (!children) directDirs.set(grandparent, children = new Set());
47
+ children.add(basename(child));
48
+ child = grandparent;
49
+ }
50
+
51
+ if (LINE_LIMIT_EXTENSIONS.has(extname(path))) {
52
+ const lines = physicalLineCount(readFileSync(path, "utf8"));
53
+ if (lines > MAX_LINES) violations.push(`${path}: ${lines} lines > ${MAX_LINES}`);
54
+ }
55
+ }
56
+
57
+ for (const path of tracked.filter((path) => dirname(path) === ".")) {
58
+ if (!ROOT_PROTOCOL_FILES.has(path)) violations.push(`repository root has unclassified file: ${path}`);
59
+ }
60
+
61
+ for (const allowed of ROOT_PROTOCOL_FILES) {
62
+ if (!tracked.includes(allowed)) continue;
63
+ // Presence is allowed, not required; this loop documents the intentional set.
64
+ }
65
+
66
+ const directories = new Set([...directFiles.keys(), ...directDirs.keys()]);
67
+ for (const directory of [...directories].sort()) {
68
+ const files = directFiles.get(directory) ?? 0;
69
+ const dirs = directDirs.get(directory)?.size ?? 0;
70
+ if (directory !== "." && files > MAX_DIRECT_FILES) {
71
+ violations.push(`${directory}: ${files} direct files > ${MAX_DIRECT_FILES}`);
72
+ }
73
+ if (dirs > MAX_DIRECT_DIRS) {
74
+ violations.push(`${directory}: ${dirs} direct directories > ${MAX_DIRECT_DIRS}`);
75
+ }
76
+ }
77
+
78
+ if (violations.length > 0) {
79
+ console.error("Architecture check failed:");
80
+ for (const violation of violations) console.error(`- ${violation}`);
81
+ process.exit(1);
82
+ }
83
+
84
+ console.log(
85
+ `Architecture check passed: ${tracked.length} tracked files; ` +
86
+ `code <= ${MAX_LINES} lines; non-root directories <= ${MAX_DIRECT_FILES} files / ${MAX_DIRECT_DIRS} directories.`,
87
+ );
88
+
89
+ function gitTrackedFiles() {
90
+ const result = spawnSync("git", ["ls-files", "-z"], {
91
+ cwd: process.cwd(),
92
+ encoding: "utf8",
93
+ windowsHide: true,
94
+ shell: false,
95
+ });
96
+ if (result.error) throw result.error;
97
+ if (result.status !== 0) throw new Error(`git ls-files failed with exit ${result.status ?? "unknown"}`);
98
+ return result.stdout.split("\0").filter(Boolean);
99
+ }
100
+
101
+ function normalizeDirectory(directory) {
102
+ return directory === "" ? "." : directory.replaceAll("\\", "/");
103
+ }
104
+
105
+ function physicalLineCount(text) {
106
+ if (text.length === 0) return 0;
107
+ const newlines = text.match(/\n/g)?.length ?? 0;
108
+ return newlines + (text.endsWith("\n") ? 0 : 1);
109
+ }
@@ -9,10 +9,15 @@ if (!npmCli) {
9
9
 
10
10
  console.log(`CI environment: ${process.platform}/${process.arch} ${process.version}`);
11
11
  runNpm(["--version"], "npm version");
12
+ runNpm(["run", "architecture:check"], "Architecture");
12
13
  runNpm(["run", "release:check"], "Release metadata");
13
14
  runNpm(["run", "typecheck"], "Typecheck");
14
15
  runNpm(["test"], "Full test suite");
15
16
  runNpm(["run", "build"], "Build");
17
+ // The traffic audit is an end-to-end wire-budget check, not a platform feature
18
+ // matrix. Run it once on Linux so regressions are gated without tripling the
19
+ // 7677/7678 server exercise across every CI operating system.
20
+ if (process.platform === "linux") runNpm(["run", "traffic:audit"], "Traffic audit");
16
21
  runNpm(["run", "lsp:interop"], "Optional LSP interoperability");
17
22
  run(process.execPath, ["dist/cli.js", "doctor"], "Doctor");
18
23