Commit e4163dd
Migrate sustainabot from ReScript to AffineScript with stdlib alignment (#204)
## Summary
Complete hand-port of the sustainabot integration layer from ReScript to
AffineScript, followed by a static-review pass to align the code against
the canonical AffineScript grammar and stdlib. This resolves the
migration initiated under issue #148's policy override (2026-05-24).
## Key Changes
### Code Migration (2026-05-24)
- **Main.affine**: Converted webhook intake and dispatch logic;
refactored JSON/Dict operations to use canonical `json::` and `dict::`
module calls; simplified nested match expressions with `unwrap_or`
helper
- **GitHubApp.affine**: Migrated JWT signing and token caching; replaced
`Bytes` type with `[Int]` array representation; refactored string
chaining to explicit intermediate bindings
- **Oikos.affine**: Ported TEA (The Elm Architecture)
model/update/subscriptions; updated type syntax (`Option[T]` →
`Option<T>`, `Array[T]` → `[T]`); added `pub` visibility modifiers
- **Report.affine**: Converted SARIF JSON construction and grade/emoji
logic; updated all `Float::to_string` and `Int::to_string` calls
- **Router.affine**: Migrated HTTP routing DSL; updated method/path
matching; changed `Array[Route]` to `[Route]`
- **Webhook.affine**: Ported HMAC-SHA256 verification and GitLab token
validation; updated `Dict[String, String]` to `[(String, String)]` tuple
list representation
- **GitHubAPI.affine**: Converted REST client with `Http::fetch`
integration; refactored JSON encoding/decoding
- **Analysis.affine**: Ported repository analysis endpoint calls;
updated JSON object construction
- **Config.affine**: Migrated environment variable access and bot mode
parsing
- **Types.affine**: Updated all type definitions with canonical syntax;
added module declaration
### Static Review Pass (2026-05-25)
- **Structural refactoring**: Split `tea/ServerTea.affine` into three
separate files (`tea/Cmd.affine`, `tea/Sub.affine`,
`tea/Runtime.affine`) because the parser has no inline `module Name {
... }` form
- **Stdlib alignment**: Replaced all non-canonical module calls with
`::` syntax (e.g., `Json.stringify` → `json::stringify`, `Dict.get` →
`dict::get`)
- **Type syntax normalization**: Converted all generic brackets from
`[T]` to `<T>` where appropriate; standardized `Option[T]` → `Option<T>`
- **Effect row cleanup**: Removed placeholder effect annotations;
aligned with `{IO}` effect model
- **Documentation**: Added `MISSING-EXTERNS.md` cataloging 20+ unbound
stdlib surfaces (Env, String extensions, Int/Float conversions, Time,
Bytes, Crypto, Base64) that the mechanical migrator must re-bind
- **Baseline update**: Removed 149 deprecated-API findings from
`.hypatia-baseline.json` (all ReScript `.res` files now migrated)
### Documentation & Housekeeping
- **README.adoc**: Restructured with macro TOC; added architecture
diagram; clarified safety-triangle decision logic
- **docs/ARCHITECTURE.md**: New authoritative source of truth for system
pipeline and component roles
- **docs/wiki-source/**: Added 5 wiki pages (Home, Architecture,
Safety-Triangle, Build-and-Run, Bot-Operations) with publication notice
- **MIGRATION-NOTES.md**: Expanded with static-review changes and
structural rework notes
- **CLAUDE.md**: Updated project conventions and architecture summary
- Removed obsolete `llm-warmup-*.md` files
## Notable Implementation Details
1. **Token caching**: Original ReScript `mut Dict` replaced with
`cache_get`/`cache_set` helper functions marked `TODO` for mechanical
migrator to wire to proper state-effect cell (issue #59)
2. **Unbound surfaces**: 20+ stdlib calls documented in
`MISSING-EXTERNS.md` rather than invented as `extern fn` declarations,
https://claude.ai/code/session_01W3PAoaqgJj3mnM8kjhEqx4
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent a117d4c commit e4163dd
44 files changed
Lines changed: 1674 additions & 1430 deletions
File tree
- .claude
- .machine_readable
- bots/sustainabot/bot-integration
- src
- tea
- docs
- archive
- wiki-source
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
8 | 11 | | |
9 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
10 | 16 | | |
11 | 17 | | |
12 | 18 | | |
13 | | - | |
| 19 | + | |
14 | 20 | | |
15 | 21 | | |
16 | | - | |
17 | | - | |
18 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
19 | 26 | | |
20 | 27 | | |
21 | 28 | | |
| |||
24 | 31 | | |
25 | 32 | | |
26 | 33 | | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
33 | 40 | | |
34 | 41 | | |
35 | 42 | | |
36 | 43 | | |
37 | 44 | | |
38 | 45 | | |
| 46 | + | |
| 47 | + | |
39 | 48 | | |
40 | 49 | | |
41 | 50 | | |
| |||
48 | 57 | | |
49 | 58 | | |
50 | 59 | | |
51 | | - | |
52 | | - | |
| 60 | + | |
| 61 | + | |
53 | 62 | | |
54 | 63 | | |
55 | 64 | | |
| |||
62 | 71 | | |
63 | 72 | | |
64 | 73 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
208 | 208 | | |
209 | 209 | | |
210 | 210 | | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
277 | | - | |
278 | | - | |
279 | | - | |
280 | | - | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
302 | | - | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | 211 | | |
356 | 212 | | |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
0 commit comments