brass-runtime 1.15.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +673 -136
  3. package/dist/agent/cli/main.cjs +40 -35
  4. package/dist/agent/cli/main.js +9 -4
  5. package/dist/agent/cli/main.mjs +9 -4
  6. package/dist/agent/index.cjs +8 -4
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +7 -3
  9. package/dist/agent/index.mjs +7 -3
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/chunk-3AYM6WPJ.js +1629 -0
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3RG5ZIWI.js +10 -0
  15. package/dist/chunk-3Y2RIUMM.js +300 -0
  16. package/dist/{chunk-VEZNF5GZ.cjs → chunk-4ROBZFL6.cjs} +130 -126
  17. package/dist/{chunk-3QMOKAS5.js → chunk-52OB2ROS.js} +9 -5
  18. package/dist/chunk-52PPNNI4.cjs +416 -0
  19. package/dist/chunk-5EC274J5.cjs +2874 -0
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/chunk-5VRJNBLZ.mjs +2874 -0
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-74ZTY6CP.js +2871 -0
  25. package/dist/chunk-76YMRMH2.cjs +777 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-4NHES7VK.mjs → chunk-7JIJOVCT.js} +27 -13
  28. package/dist/chunk-A2OM6NEH.mjs +194 -0
  29. package/dist/chunk-AGR5B2BC.cjs +683 -0
  30. package/dist/chunk-AVNQLJ5V.js +777 -0
  31. package/dist/chunk-B33ICAKP.js +313 -0
  32. package/dist/{chunk-ELOOF35R.mjs → chunk-B5JD23U7.mjs} +1 -1
  33. package/dist/chunk-BABBZK4Y.js +2024 -0
  34. package/dist/chunk-C3MDXTRZ.js +354 -0
  35. package/dist/chunk-CIZFIMK5.js +2193 -0
  36. package/dist/chunk-CZIVE6NT.cjs +354 -0
  37. package/dist/chunk-DNFJLJMW.mjs +354 -0
  38. package/dist/chunk-DNFO2EIZ.mjs +777 -0
  39. package/dist/chunk-EJ6BPYVR.mjs +416 -0
  40. package/dist/chunk-ENKODRU3.cjs +2193 -0
  41. package/dist/chunk-EOC4UHBS.mjs +229 -0
  42. package/dist/{chunk-BMH5AV44.js → chunk-FH2X7BVP.js} +756 -440
  43. package/dist/{chunk-PPUXIH5R.js → chunk-FHQGHPMO.mjs} +27 -13
  44. package/dist/{chunk-TGIFUAK4.cjs → chunk-GLE2WY7Z.cjs} +951 -635
  45. package/dist/{chunk-BDF4AMWX.mjs → chunk-GYM3LLGS.mjs} +756 -440
  46. package/dist/chunk-HLWLMW2F.mjs +2024 -0
  47. package/dist/chunk-JF5WGYJJ.cjs +194 -0
  48. package/dist/chunk-KH4SYAOS.mjs +1629 -0
  49. package/dist/chunk-KN32XNTH.mjs +313 -0
  50. package/dist/chunk-KQLYONSE.cjs +2871 -0
  51. package/dist/{chunk-STVLQ3XD.cjs → chunk-KZJQ723N.cjs} +92 -78
  52. package/dist/chunk-L2SYFEBS.js +194 -0
  53. package/dist/chunk-L6VB5N7Q.cjs +104 -0
  54. package/dist/{chunk-K6M7MDZ4.mjs → chunk-MBEJI5HF.mjs} +9 -5
  55. package/dist/chunk-MIIYDLGM.js +2874 -0
  56. package/dist/chunk-MOO4L7F4.mjs +104 -0
  57. package/dist/chunk-MT3OWDPC.mjs +2193 -0
  58. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  59. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  60. package/dist/chunk-PD4EJTQC.cjs +229 -0
  61. package/dist/chunk-PWC3RBQE.mjs +300 -0
  62. package/dist/chunk-Q2I37RP3.cjs +1629 -0
  63. package/dist/chunk-RKGKFN2A.js +416 -0
  64. package/dist/{chunk-R3R2FVLG.cjs → chunk-SA6HUJVI.cjs} +5 -5
  65. package/dist/chunk-TRM4JUZQ.js +104 -0
  66. package/dist/chunk-UB4B6OFY.js +370 -0
  67. package/dist/{chunk-TO7IKXYT.js → chunk-UCUBNWM2.js} +1 -1
  68. package/dist/chunk-VN44DYYT.cjs +2024 -0
  69. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  70. package/dist/client-CZHU674n.d.ts +820 -0
  71. package/dist/core/index.cjs +198 -4
  72. package/dist/core/index.d.ts +311 -212
  73. package/dist/core/index.js +237 -43
  74. package/dist/core/index.mjs +237 -43
  75. package/dist/{effect-CMOQKX8y.d.ts → effect-DIUHZ9IN.d.ts} +195 -1
  76. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  77. package/dist/effectRunner-L4S7IPT3.js +8 -0
  78. package/dist/effectRunner-NNGG75QA.mjs +8 -0
  79. package/dist/http/index.cjs +1227 -2971
  80. package/dist/http/index.d.ts +826 -280
  81. package/dist/http/index.js +1089 -2833
  82. package/dist/http/index.mjs +1089 -2833
  83. package/dist/http/testing.cjs +161 -0
  84. package/dist/http/testing.d.ts +43 -0
  85. package/dist/http/testing.js +161 -0
  86. package/dist/http/testing.mjs +161 -0
  87. package/dist/index.cjs +486 -250
  88. package/dist/index.d.ts +87 -95
  89. package/dist/index.js +391 -155
  90. package/dist/index.mjs +391 -155
  91. package/dist/observability/index.cjs +162 -0
  92. package/dist/observability/index.d.ts +152 -0
  93. package/dist/observability/index.js +162 -0
  94. package/dist/observability/index.mjs +162 -0
  95. package/dist/perf/cli.cjs +401 -0
  96. package/dist/perf/cli.d.ts +1 -0
  97. package/dist/perf/cli.js +401 -0
  98. package/dist/perf/cli.mjs +401 -0
  99. package/dist/perf/index.cjs +141 -0
  100. package/dist/perf/index.d.ts +483 -0
  101. package/dist/perf/index.js +141 -0
  102. package/dist/perf/index.mjs +141 -0
  103. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  104. package/dist/schema/index.cjs +29 -0
  105. package/dist/schema/index.d.ts +179 -0
  106. package/dist/schema/index.js +29 -0
  107. package/dist/schema/index.mjs +29 -0
  108. package/dist/server-GJPg8ZSG.d.ts +675 -0
  109. package/dist/{stream-FQm9h4Mg.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  110. package/dist/tracer-Hwt1cl7h.d.ts +189 -0
  111. package/dist/tracing-DqbTKGcf.d.ts +148 -0
  112. package/docs/ARCHITECTURE.md +292 -0
  113. package/docs/README.md +63 -0
  114. package/docs/adr/0001-ai-context-pack.md +32 -0
  115. package/docs/agent-apply-mode.md +104 -0
  116. package/docs/agent-approvals.md +110 -0
  117. package/docs/agent-batch.md +185 -0
  118. package/docs/agent-boundaries.md +112 -0
  119. package/docs/agent-chat-sessions.md +160 -0
  120. package/docs/agent-ci.md +17 -0
  121. package/docs/agent-cli.md +405 -0
  122. package/docs/agent-config.md +480 -0
  123. package/docs/agent-context-discovery.md +159 -0
  124. package/docs/agent-copilot-like-dx.md +126 -0
  125. package/docs/agent-declarative-optimized-planning.md +138 -0
  126. package/docs/agent-dx.md +224 -0
  127. package/docs/agent-env-files.md +126 -0
  128. package/docs/agent-follow-up-context.md +43 -0
  129. package/docs/agent-global-usage.md +180 -0
  130. package/docs/agent-init.md +109 -0
  131. package/docs/agent-install-and-configure.md +516 -0
  132. package/docs/agent-language-workspace-ux.md +99 -0
  133. package/docs/agent-llm-adapters.md +123 -0
  134. package/docs/agent-local-install.md +190 -0
  135. package/docs/agent-local-tests.md +51 -0
  136. package/docs/agent-observability.md +155 -0
  137. package/docs/agent-patch-quality-loop.md +162 -0
  138. package/docs/agent-presets.md +22 -0
  139. package/docs/agent-project-commands.md +237 -0
  140. package/docs/agent-project-intelligence.md +156 -0
  141. package/docs/agent-redaction.md +18 -0
  142. package/docs/agent-release-readiness.md +76 -0
  143. package/docs/agent-rollback-safety.md +162 -0
  144. package/docs/agent-rollback.md +23 -0
  145. package/docs/agent-run-artifacts.md +16 -0
  146. package/docs/agent-vscode-auto-discovery.md +137 -0
  147. package/docs/agent-vscode-batch-runner.md +100 -0
  148. package/docs/agent-vscode-chat-layout.md +90 -0
  149. package/docs/agent-vscode-clean-install.md +147 -0
  150. package/docs/agent-vscode-code-actions.md +70 -0
  151. package/docs/agent-vscode-diff-preview.md +45 -0
  152. package/docs/agent-vscode-inline-assist.md +56 -0
  153. package/docs/agent-vscode-install.md +186 -0
  154. package/docs/agent-vscode-model-setup.md +97 -0
  155. package/docs/agent-vscode-patch-preview.md +92 -0
  156. package/docs/agent-vscode-problems.md +79 -0
  157. package/docs/agent-vscode-project-dashboard.md +106 -0
  158. package/docs/agent-vscode-run-history.md +92 -0
  159. package/docs/agent-vscode-ux.md +73 -0
  160. package/docs/ai/INVARIANTS.md +84 -0
  161. package/docs/ai/PROJECT_MAP.md +338 -0
  162. package/docs/ai/PUBLIC_API.md +336 -0
  163. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  164. package/docs/api-polish.md +37 -0
  165. package/docs/cancellation.md +162 -0
  166. package/docs/coverage.md +46 -0
  167. package/docs/getting-started.md +159 -0
  168. package/docs/guides/README.md +40 -0
  169. package/docs/guides/circuit-breaker.md +89 -0
  170. package/docs/guides/error-handling.md +91 -0
  171. package/docs/guides/getting-started.md +107 -0
  172. package/docs/guides/layers.md +189 -0
  173. package/docs/guides/metrics.md +101 -0
  174. package/docs/guides/resource-management.md +141 -0
  175. package/docs/guides/retry.md +215 -0
  176. package/docs/guides/semaphore.md +66 -0
  177. package/docs/guides/streams.md +117 -0
  178. package/docs/guides/supervisors.md +98 -0
  179. package/docs/guides/testing.md +162 -0
  180. package/docs/guides/tracing.md +71 -0
  181. package/docs/http-recipes.md +399 -0
  182. package/docs/http.md +749 -0
  183. package/docs/modules.md +285 -0
  184. package/docs/observability-collector-smoke.md +31 -0
  185. package/docs/observability-framework-examples.md +98 -0
  186. package/docs/observability.md +542 -0
  187. package/docs/otel-collector-smoke.yaml +27 -0
  188. package/docs/performance-profiler.md +199 -0
  189. package/docs/production-readiness.md +73 -0
  190. package/docs/recipes/README.md +12 -0
  191. package/docs/recipes/http-server.md +45 -0
  192. package/docs/recipes/layers.md +44 -0
  193. package/docs/recipes/performance.md +47 -0
  194. package/docs/recipes/runtime.md +41 -0
  195. package/docs/recipes/testing.md +41 -0
  196. package/docs/release.md +53 -0
  197. package/docs/wasm-bounded-queues.md +44 -0
  198. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  199. package/docs/wasm-fiber-engine.md +117 -0
  200. package/docs/wasm-scheduler-state-machine.md +122 -0
  201. package/docs/wasm-stream-chunks.md +54 -0
  202. package/package.json +48 -2
  203. package/dist/chunk-AR22SXML.js +0 -1043
  204. package/dist/chunk-BDYEENHT.js +0 -224
  205. package/dist/chunk-JFPU5GQI.mjs +0 -1043
  206. package/dist/chunk-MS34J5LY.cjs +0 -224
  207. package/dist/chunk-UMAZLXAB.mjs +0 -224
  208. package/dist/chunk-XPZNXSVN.cjs +0 -1043
  209. package/dist/tracing-DNT9jEbr.d.ts +0 -106
@@ -0,0 +1,123 @@
1
+ # Agent LLM adapters
2
+
3
+ `src/agent` keeps LLM providers behind the small `LLM` capability:
4
+
5
+ ```ts
6
+ export type LLM = {
7
+ readonly complete: (request: LLMRequest) => Async<unknown, AgentError, LLMResponse>;
8
+ };
9
+ ```
10
+
11
+ Adapters must return `Async` and must be cancelable. They should not leak provider-specific request or response shapes into the agent loop.
12
+
13
+ ## Provider selection in the CLI
14
+
15
+ The local CLI chooses a provider from environment variables:
16
+
17
+ ```bash
18
+ BRASS_LLM_PROVIDER=google # or gemini
19
+ BRASS_LLM_PROVIDER=openai-compatible
20
+ BRASS_LLM_PROVIDER=fake
21
+ ```
22
+
23
+ If `BRASS_LLM_PROVIDER` is omitted, the CLI auto-detects providers in this order:
24
+
25
+ 1. Google Gemini, when `BRASS_GOOGLE_API_KEY`, `GOOGLE_API_KEY`, or `GEMINI_API_KEY` exists.
26
+ 2. OpenAI-compatible, when both `BRASS_LLM_ENDPOINT` and `BRASS_LLM_API_KEY` exist.
27
+ 3. Fake LLM, as a no-network fallback.
28
+
29
+ ## Google Gemini / Generative Language API
30
+
31
+ Use the native Google adapter:
32
+
33
+ ```ts
34
+ import { makeGoogleGenerativeAILLM } from "brass-runtime/agent";
35
+
36
+ const llm = makeGoogleGenerativeAILLM({
37
+ apiKey: process.env.GEMINI_API_KEY!,
38
+ model: "gemini-2.5-flash",
39
+ });
40
+ ```
41
+
42
+ CLI example:
43
+
44
+ ```bash
45
+ export BRASS_LLM_PROVIDER=google
46
+ export GEMINI_API_KEY="..."
47
+ export BRASS_GOOGLE_MODEL="gemini-2.5-flash"
48
+
49
+ npx tsx src/agent/cli/main.ts "fix the failing tests"
50
+ ```
51
+
52
+ The same keys can live in `.env` or `.brass-agent.env` in the workspace; the
53
+ CLI auto-loads supported agent env keys before choosing the provider.
54
+
55
+ Supported Google-specific variables:
56
+
57
+ ```bash
58
+ BRASS_GOOGLE_API_KEY # preferred explicit key for brass-agent
59
+ GOOGLE_API_KEY # supported by Google SDKs; also accepted here
60
+ GEMINI_API_KEY # supported by Google SDKs; also accepted here
61
+ BRASS_GOOGLE_MODEL # defaults to gemini-2.5-flash
62
+ BRASS_GOOGLE_API_VERSION # defaults to v1beta
63
+ BRASS_GOOGLE_BASE_URL # defaults to https://generativelanguage.googleapis.com
64
+ BRASS_GOOGLE_ENDPOINT # full generateContent endpoint override
65
+ BRASS_GOOGLE_SYSTEM_INSTRUCTION
66
+ BRASS_GOOGLE_TEMPERATURE
67
+ BRASS_GOOGLE_TOP_P
68
+ BRASS_GOOGLE_TOP_K
69
+ BRASS_GOOGLE_MAX_OUTPUT_TOKENS
70
+ ```
71
+
72
+ The adapter uses `models.generateContent` with the `x-goog-api-key` header and maps Gemini `candidates[].content.parts[].text` into `LLMResponse.content`.
73
+
74
+ ## OpenAI-compatible
75
+
76
+ Use the existing adapter:
77
+
78
+ ```bash
79
+ export BRASS_LLM_PROVIDER=openai-compatible
80
+ export BRASS_LLM_ENDPOINT="https://.../chat/completions"
81
+ export BRASS_LLM_API_KEY="..."
82
+ export BRASS_LLM_MODEL="..."
83
+ ```
84
+
85
+ ## Fake
86
+
87
+ Use this for offline smoke tests:
88
+
89
+ ```bash
90
+ export BRASS_LLM_PROVIDER=fake
91
+ npx tsx src/agent/cli/main.ts "fix the failing tests"
92
+ ```
93
+
94
+ You can also force a deterministic fake response, including a fenced diff block:
95
+
96
+ ~~~bash
97
+ export BRASS_LLM_PROVIDER=fake
98
+ export BRASS_FAKE_LLM_RESPONSE='```diff
99
+ --- a/hello.txt
100
+ +++ b/hello.txt
101
+ @@ -1 +1 @@
102
+ -old
103
+ +new
104
+ ```'
105
+ ~~~
106
+
107
+ ## Config-file selection
108
+
109
+ P7 also lets the CLI select an adapter through `.brass-agent.json`:
110
+
111
+ ```json
112
+ {
113
+ "llm": {
114
+ "provider": "google",
115
+ "model": "gemini-2.5-flash",
116
+ "apiKeyEnv": "GEMINI_API_KEY"
117
+ }
118
+ }
119
+ ```
120
+
121
+ Environment variables still override config values. Secrets should stay in the
122
+ environment; the config loader rejects `llm.apiKey` and expects `llm.apiKeyEnv`
123
+ instead.
@@ -0,0 +1,190 @@
1
+ # Brass Agent local install and doctor
2
+
3
+ > For the end-to-end setup flow, see [Brass Agent install and configure](./agent-install-and-configure.md).
4
+
5
+ P23 intentionally avoids CI/release automation. It focuses on making local DX
6
+ boring: build the CLI, package/install the VS Code extension, point the extension
7
+ at the local CLI, and diagnose the setup.
8
+
9
+ ## One-command local VS Code install
10
+
11
+ From the repository root:
12
+
13
+ ```bash
14
+ npm run agent:vscode:install
15
+ ```
16
+
17
+ That script performs the local install flow:
18
+
19
+ ```txt
20
+ npm install # only if root node_modules is missing
21
+ npm run build # builds dist/agent/cli/main.cjs
22
+ npm install # inside extensions/vscode-brass-agent, if needed
23
+ npm run compile # extension TypeScript
24
+ npm run package:vsix # creates vscode-brass-agent-*.vsix
25
+ code --install-extension # installs the VSIX locally
26
+ write .vscode/settings.json # points brassAgent.command at the built local CLI
27
+ ```
28
+
29
+ The setting it writes is:
30
+
31
+ ```json
32
+ {
33
+ "brassAgent.command": "/absolute/path/to/brass-runtime/dist/agent/cli/main.cjs"
34
+ }
35
+ ```
36
+
37
+ That means the extension can run the exact local CLI build without requiring a
38
+ global npm install.
39
+
40
+ ## Global CLI for many projects
41
+
42
+ To use `brass-agent` outside the `brass-runtime` checkout:
43
+
44
+ ```bash
45
+ npm run agent:link
46
+ ```
47
+
48
+ Then from any project:
49
+
50
+ ```bash
51
+ brass-agent --where
52
+ brass-agent --doctor
53
+ brass-agent --preset inspect
54
+ ```
55
+
56
+ To make VS Code work through that global command instead of an absolute local path:
57
+
58
+ ```bash
59
+ npm run agent:vscode:install:global
60
+ ```
61
+
62
+ That command runs the global link flow and installs the VS Code extension with `brassAgent.command = "brass-agent"`.
63
+
64
+ To remove only the global CLI link/install:
65
+
66
+ ```bash
67
+ npm run agent:unlink
68
+ ```
69
+
70
+ To remove the VS Code extension, workspace settings/storage, generated VSIX files, and the global CLI link/install:
71
+
72
+ ```bash
73
+ npm run agent:vscode:uninstall:global
74
+ ```
75
+
76
+ To do a clean global reinstall:
77
+
78
+ ```bash
79
+ npm run agent:vscode:reinstall:global
80
+ ```
81
+
82
+ ## Package only
83
+
84
+ To build/package the extension without installing it into VS Code:
85
+
86
+ ```bash
87
+ npm run agent:vscode:package
88
+ ```
89
+
90
+ This is useful when you want to manually install from VS Code via:
91
+
92
+ ```txt
93
+ Extensions view
94
+ -> Views and More Actions...
95
+ -> Install from VSIX...
96
+ ```
97
+
98
+ ## Install script options
99
+
100
+ The underlying script is:
101
+
102
+ ```bash
103
+ node scripts/install-vscode-extension.mjs
104
+ ```
105
+
106
+ Useful options:
107
+
108
+ ```bash
109
+ node scripts/install-vscode-extension.mjs --dry-run
110
+ node scripts/install-vscode-extension.mjs --no-code-install
111
+ node scripts/install-vscode-extension.mjs --no-settings
112
+ node scripts/install-vscode-extension.mjs --workspace ../some-project
113
+ node scripts/install-vscode-extension.mjs --use-global-command
114
+ node scripts/install-vscode-extension.mjs --command brass-agent
115
+ node scripts/install-vscode-extension.mjs --code "code-insiders"
116
+ ```
117
+
118
+ Use `--workspace` when you want the script to write `.vscode/settings.json` into
119
+ a different project than the `brass-runtime` checkout. Use `--use-global-command`
120
+ when `brass-agent` is available on PATH and you do not want workspace settings to
121
+ point at an absolute `dist/agent/cli/main.cjs` path.
122
+
123
+ ## Doctor
124
+
125
+ Run:
126
+
127
+ ```bash
128
+ npm run agent:doctor
129
+ ```
130
+
131
+ or after building/installing:
132
+
133
+ ```bash
134
+ brass-agent --doctor
135
+ ```
136
+
137
+ The doctor checks:
138
+
139
+ ```txt
140
+ Node.js / npm
141
+ git
142
+ ripgrep / rg
143
+ workspace package.json and scripts
144
+ inferred package manager
145
+ LLM provider environment
146
+ .brass-agent.json / brass-agent.config.json discovery
147
+ VS Code `code` CLI
148
+ VS Code workspace setting brassAgent.command
149
+ local CLI build artifact
150
+ VS Code extension build / VSIX package
151
+ ```
152
+
153
+ JSON output is available for scripts:
154
+
155
+ ```bash
156
+ brass-agent --doctor --json
157
+ ```
158
+
159
+ ## Why this is not CI
160
+
161
+ This is deliberately local-first. It gives us repeatable commands that a person
162
+ can run before we add workflows:
163
+
164
+ ```bash
165
+ npm run agent:vscode:install
166
+ npm run agent:doctor
167
+ ```
168
+
169
+ Later, CI can reuse the same install/build/doctor concepts, but P23 does not add
170
+ GitHub Actions or release automation.
171
+
172
+ ## Initialize a workspace first
173
+
174
+ For a new project, bootstrap local config before deeper DX setup:
175
+
176
+ ```bash
177
+ brass-agent --init
178
+ brass-agent --doctor
179
+ ```
180
+
181
+ The VS Code extension also contributes `Brass Agent: Initialize Workspace`, which runs the same init flow from the command palette.
182
+
183
+ ## Env files
184
+
185
+ `brass-agent --doctor` auto-loads supported agent keys from `.brass-agent.env`, `.env.local`, and `.env` in the workspace. Use `--env-file PATH` to choose a file or `--no-env-file` to disable this behavior. See [Agent env files](./agent-env-files.md).
186
+
187
+
188
+ ## VS Code auto-discovery
189
+
190
+ The VS Code extension can now use `brassAgent.command = "auto"` and prefer its bundled CLI, so you can open any repo and use Brass Agent without linking the CLI globally. See [VS Code auto-discovery](./agent-vscode-auto-discovery.md).
@@ -0,0 +1,51 @@
1
+ # Brass Agent local tests
2
+
3
+ P36 adds local smoke-test scripts for dogfooding without CI.
4
+
5
+ These tests are intentionally local-first. They do not publish artifacts, do not require a real LLM provider, and do not need GitHub Actions.
6
+
7
+ ## Smoke test
8
+
9
+ Build first, then run:
10
+
11
+ ```bash
12
+ npm run agent:test:smoke
13
+ ```
14
+
15
+ Or run the full local flow:
16
+
17
+ ```bash
18
+ npm run agent:test:local
19
+ ```
20
+
21
+ `agent:test:local` runs:
22
+
23
+ ```txt
24
+ npm run build
25
+ node scripts/agent-local-smoke.mjs
26
+ ```
27
+
28
+ ## What the smoke test validates
29
+
30
+ The smoke test creates a temporary project and checks:
31
+
32
+ ```txt
33
+ - the built CLI exists
34
+ - read-only inspect can finish with fake LLM
35
+ - apply mode can use fake LLM diff output
36
+ - patch preview/apply plumbing can update a file through the CLI
37
+ - validation can pass after the patch
38
+ ```
39
+
40
+ It uses:
41
+
42
+ ```txt
43
+ BRASS_LLM_PROVIDER=fake
44
+ BRASS_FAKE_LLM_RESPONSE=<controlled unified diff>
45
+ ```
46
+
47
+ No real API key is required.
48
+
49
+ ## Why no CI yet
50
+
51
+ This is a local stabilization step only. CI and release automation remain intentionally deferred until the agent UX has been dogfooded more heavily.
@@ -0,0 +1,155 @@
1
+ # Brass Agent observability
2
+
3
+ `brass-agent` emits a typed event stream while the agent loop runs.
4
+
5
+ The event stream is intentionally modeled as a capability of the agent environment:
6
+
7
+ ```ts
8
+ type AgentEnv = {
9
+ fs: FileSystem;
10
+ shell: Shell;
11
+ llm: LLM;
12
+ patch: PatchService;
13
+ permissions: PermissionService;
14
+ approvals?: ApprovalService;
15
+ events?: AgentEventSink;
16
+ };
17
+ ```
18
+
19
+ The core runtime does not know about the agent. The agent depends on the runtime and exposes its own higher-level observability events.
20
+
21
+ ## Invariant
22
+
23
+ Observability must never change agent semantics.
24
+
25
+ If an event sink throws, the agent ignores the sink failure and continues. Event sinks are best-effort and should not be used for control flow.
26
+
27
+ ## Event lifecycle
28
+
29
+ A normal run emits events in this order:
30
+
31
+ ```txt
32
+ agent.run.started
33
+ agent.action.started
34
+ agent.action.completed
35
+ agent.observation.recorded
36
+ ...
37
+ agent.run.completed
38
+ ```
39
+
40
+ If a tool fails, the action emits:
41
+
42
+ ```txt
43
+ agent.action.started
44
+ agent.action.failed
45
+ agent.observation.recorded
46
+ ```
47
+
48
+ Some important failures also emit specialized events:
49
+
50
+ ```txt
51
+ agent.tool.timeout
52
+ agent.permission.denied
53
+ agent.approval.requested
54
+ agent.approval.resolved
55
+ ```
56
+
57
+ Approval events are emitted around `ApprovalService.request(...)`. They report
58
+ that an action asked for human or policy approval and whether that approval was
59
+ granted or rejected.
60
+
61
+ When a patch is applied, the stream also emits:
62
+
63
+ ```txt
64
+ agent.patch.applied
65
+ ```
66
+
67
+ ## CLI output
68
+
69
+ Human output now uses the live event stream by default:
70
+
71
+ ```bash
72
+ brass-agent "fix the failing tests"
73
+ ```
74
+
75
+ Example shape:
76
+
77
+ ```txt
78
+ brass-agent propose
79
+ workspace: /repo
80
+ goal: fix the failing tests
81
+
82
+ → read package.json
83
+ ✓ read package.json 3ms
84
+ → check pnpm-lock.yaml
85
+ ✓ found pnpm-lock.yaml 2ms
86
+ → pnpm test
87
+ ! pnpm test exited 1 1234ms
88
+ → llm.plan
89
+ ✓ llm.plan responded 2400ms
90
+ → propose patch
91
+ ✓ patch proposed 1ms
92
+ → finish
93
+ ✓ done 1ms
94
+
95
+ phase: done
96
+ steps: 5
97
+ ```
98
+
99
+ The old full-state debug output is still available:
100
+
101
+ ```bash
102
+ brass-agent --json "fix the failing tests"
103
+ ```
104
+
105
+ For quick machine-readable streaming, use event-only JSON Lines:
106
+
107
+ ```bash
108
+ brass-agent --events-json "fix the failing tests"
109
+ ```
110
+
111
+ This prints one compact `AgentEvent` per line.
112
+
113
+ For editor integrations and other clients, prefer the protocol stream:
114
+
115
+ ```bash
116
+ brass-agent --protocol-json "fix the failing tests"
117
+ ```
118
+
119
+ This prints newline-delimited messages with `protocol: "brass-agent"`, `version: 1`, event messages, and a final-state message. See [Agent DX surfaces](./agent-dx.md).
120
+
121
+ ## Programmatic usage
122
+
123
+ ```ts
124
+ import {
125
+ runAgent,
126
+ type AgentEnv,
127
+ type AgentEventSink,
128
+ } from "brass-runtime/agent";
129
+
130
+ const events: AgentEventSink = {
131
+ emit(event) {
132
+ console.log(event.type, event);
133
+ },
134
+ };
135
+
136
+ const env: AgentEnv = {
137
+ fs,
138
+ shell,
139
+ patch,
140
+ llm,
141
+ permissions,
142
+ approvals,
143
+ events,
144
+ };
145
+ ```
146
+
147
+ ## Privacy and output size
148
+
149
+ The CLI compacts large payloads in `--events-json` mode, including file contents, LLM prompts, LLM responses, shell output, and patches.
150
+
151
+ Programmatic event sinks receive the typed event values directly. If you forward them to logs, apply your own redaction policy.
152
+
153
+ ## Boundary rule
154
+
155
+ `src/core` must not import agent events. Agent observability lives in `src/agent` and is built on top of runtime semantics.
@@ -0,0 +1,162 @@
1
+ # Agent patch quality loop
2
+
3
+ P13 adds a bounded repair loop for generated patches.
4
+
5
+ The previous apply flow was one-shot:
6
+
7
+ ```txt
8
+ llm.plan
9
+ -> patch.apply
10
+ -> validation commands
11
+ -> finish
12
+ ```
13
+
14
+ The new flow can perform one or more repair attempts when the generated patch
15
+ fails to apply or when validation still fails after apply:
16
+
17
+ ```txt
18
+ llm.plan
19
+ -> patch.apply
20
+ -> validation commands
21
+ -> if validation fails: llm.patch
22
+ -> patch.apply
23
+ -> validation commands
24
+ -> finish
25
+ ```
26
+
27
+ The loop is intentionally small and bounded. It is a quality pass, not an
28
+ unbounded autonomous edit loop.
29
+
30
+ ## Exact patch safety
31
+
32
+ Runs started with an explicit patch file stay exact:
33
+
34
+ ```bash
35
+ brass-agent --apply-patch-file ./approved.diff --yes "apply approved patch"
36
+ ```
37
+
38
+ For these runs, repair is disabled. That preserves the VS Code patch preview
39
+ invariant:
40
+
41
+ ```txt
42
+ preview patch A
43
+ -> approve patch A
44
+ -> apply exactly patch A
45
+ ```
46
+
47
+ The agent must not silently generate and apply patch B after the user approved
48
+ patch A. To allow the agent to repair its own generated patches, use normal
49
+ write mode instead:
50
+
51
+ ```bash
52
+ brass-agent --apply "fix the failing tests"
53
+ ```
54
+
55
+ ## Configuration
56
+
57
+ Configure the loop in `.brass-agent.json`:
58
+
59
+ ```json
60
+ {
61
+ "patchQuality": {
62
+ "enabled": true,
63
+ "maxRepairAttempts": 1
64
+ }
65
+ }
66
+ ```
67
+
68
+ Defaults:
69
+
70
+ ```txt
71
+ enabled: true
72
+ maxRepairAttempts: 1
73
+ ```
74
+
75
+ Disable repairs entirely:
76
+
77
+ ```json
78
+ {
79
+ "patchQuality": {
80
+ "enabled": false
81
+ }
82
+ }
83
+ ```
84
+
85
+ Allow two repair calls after the initial generated patch:
86
+
87
+ ```json
88
+ {
89
+ "patchQuality": {
90
+ "maxRepairAttempts": 2
91
+ }
92
+ }
93
+ ```
94
+
95
+ A value of `0` means “apply once, validate once, do not ask for repairs.”
96
+
97
+ ## What counts as a repair attempt?
98
+
99
+ Only LLM calls with purpose `patch` count as repair attempts.
100
+
101
+ The initial planning call is still `llm.plan`:
102
+
103
+ ```txt
104
+ llm.plan # initial diagnosis / patch proposal
105
+ llm.patch # repair attempt 1
106
+ llm.patch # repair attempt 2, if configured
107
+ ```
108
+
109
+ ## What triggers a repair?
110
+
111
+ A repair can be requested when all of these are true:
112
+
113
+ 1. the agent is in `write` or `autonomous` mode
114
+ 2. the patch came from the agent, not from `--apply-patch-file`
115
+ 3. `patchQuality.enabled` is not `false`
116
+ 4. remaining repair budget is greater than zero
117
+ 5. either:
118
+ - `patch.apply` failed, or
119
+ - validation commands ran after `patch.applied` and at least one failed
120
+
121
+ Permission denials, approval rejections, and non-patch tool failures do not
122
+ trigger patch repair.
123
+
124
+ ## Boundaries
125
+
126
+ The repair loop does not change the core runtime boundary:
127
+
128
+ ```txt
129
+ src/core
130
+
131
+ src/agent decides llm.patch / patch.apply
132
+
133
+ src/agent/cli configures patchQuality
134
+ ```
135
+
136
+ Repair is just more agent logic expressed as normal actions:
137
+
138
+ ```txt
139
+ AgentAction(llm.complete purpose=patch)
140
+ -> LLM capability
141
+ -> Observation(llm.response purpose=patch)
142
+ -> AgentAction(patch.apply)
143
+ -> PermissionService / ApprovalService
144
+ -> PatchService
145
+ -> validation commands
146
+ ```
147
+
148
+ No side effects are executed outside the `Async` tool pipeline.
149
+
150
+
151
+ ## Relationship with rollback safety
152
+
153
+ P14 runs after the patch quality loop. If validation still fails and no repair
154
+ attempts remain, rollback safety can reverse generated patches through
155
+ `patch.rollback`. This keeps repair and restore as separate decisions:
156
+
157
+ ```txt
158
+ repair budget remains -> llm.patch
159
+ repair budget exhausted -> optional patch.rollback
160
+ ```
161
+
162
+ See [Agent automatic rollback safety](./agent-rollback-safety.md).
@@ -0,0 +1,22 @@
1
+ # Brass Agent presets
2
+
3
+ P20 adds built-in DX presets for common developer workflows.
4
+
5
+ ```bash
6
+ brass-agent --preset fix-tests
7
+ brass-agent --preset inspect
8
+ brass-agent --preset typecheck
9
+ brass-agent --preset lint
10
+ ```
11
+
12
+ A preset only supplies a default goal and, for `inspect`, defaults to `read-only` when no `--mode` was explicitly provided. Explicit goal text and flags still win.
13
+
14
+ VS Code also exposes preset commands:
15
+
16
+ ```txt
17
+ Brass Agent: Fix Tests
18
+ Brass Agent: Typecheck
19
+ Brass Agent: Lint
20
+ ```
21
+
22
+ The VS Code commands still use the preview-first flow: generate patch proposal, show Webview, then apply the exact reviewed patch through `brass-agent`.