Skip to content

Commit 0db9fd5

Browse files
feat(sustainabot): migrate bot-integration from ReScript to AffineScr… (#199)
…ipt (#148) Hand-port of bots/sustainabot/bot-integration/ from ReScript to AffineScript under explicit policy override of issue #148 (which previously forbade hand-porting ahead of the upstream mechanical migrator). Scope: - 11 .res files re-expressed as .affine (Types, Config, Webhook, Analysis, GitHubAPI, GitHubApp, Report, Router, Oikos, Main, tea/ServerTea). - Deleted .res/.res.js sources, lib/ocaml/ duplicates, bindings/, the vendored rescript-runtime/ Belt snapshot, and rescript.json. - Updated package.json + deno.json to target the AffineScript toolchain. - Added MIGRATION-NOTES.md documenting placeholders pending #161 (Json), #162 (Dict/Map), and Phase-3 of the migration assistant (#57/#314). Also unblocks PR #198: the governance "Language / package anti-pattern policy" check failed there because the .hypatia-ignore file the PR added isn't read by the upstream reusable workflow in hyperpolymath/standards. Removing the .res sources removes the root cause that the rule was firing on, so re-running the check on a main rebased over this commit should pass. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6d5f70b commit 0db9fd5

394 files changed

Lines changed: 2111 additions & 70884 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!-- SPDX-License-Identifier: PMPL-1.0-or-later -->
2+
# ReScript → AffineScript Migration (issue #148)
3+
4+
This subtree was migrated from ReScript to AffineScript on 2026-05-24 by a
5+
**hand-port under explicit policy override** of issue #148's
6+
"do-not-hand-port-ahead-of-the-compiler" rule.
7+
8+
## Scope of migration
9+
10+
- All `.res` / `.res.js` under `src/`, `src/tea/`, `bindings/`, and
11+
`lib/ocaml/` were deleted.
12+
- The `rescript-runtime/` vendored Belt runtime was deleted.
13+
- `rescript.json` was deleted.
14+
- `package.json` and `deno.json` were updated to target the AffineScript
15+
toolchain instead of `rescript build` / `.res.js` outputs.
16+
- The 11 in-scope `.res` files were re-expressed as `.affine`:
17+
`Types`, `Config`, `Webhook`, `Analysis`, `GitHubAPI`, `GitHubApp`,
18+
`Report`, `Router`, `Oikos`, `Main`, and `tea/ServerTea`.
19+
20+
## Known caveats (must be verified by the real mechanical migrator)
21+
22+
The hand-port was done without an AffineScript compiler available to the
23+
porter, against the canonical README spec only. Several pieces are
24+
educated guesses that the upstream Phase-3 migration assistant
25+
(affinescript#57 / PR #314) is expected to redo:
26+
27+
1. **`Json` and `Dict` are placeholder names** in many type signatures.
28+
The portable `Json` primitive is tracked by affinescript#161 (OPEN)
29+
and `Dict`/`Map` by #162 (OPEN). Once those land, the placeholders
30+
need to be re-pointed at the canonical stdlib names.
31+
2. **Effect rows** use a conservative `-{IO + Http + Crypto + Exn[E]}->`
32+
shape. These need narrowing against the actual effect declarations
33+
in the stdlib.
34+
3. **TEA runtime (`tea/ServerTea.affine`)** uses `mut` cells and
35+
mutually-recursive closures. The borrow checker may force this into
36+
a single-owner / handler-state shape — exact form to be settled by
37+
the actual checker.
38+
4. **JWT crypto chain (`GitHubApp.affine`)** assumes Web Crypto-derived
39+
stdlib bindings (`Crypto.import_key_pkcs8`,
40+
`Crypto.sign_with_algorithm`). Real binding names will land with
41+
`#103` (Async-extern ABI — closed 2026-05-18) once the canonical
42+
stdlib surface is published.
43+
5. **Bindings deleted** (`bindings/Deno.res`, `bindings/Fetch.res`) —
44+
their callers now reference target-agnostic stdlib names
45+
(`Http.fetch`, `Env.get`, `Console.log`, etc.). The compiler's
46+
target-binding layer is expected to lower these per backend.
47+
48+
## Re-port checklist (when affinescript#57 Phase 3 lands)
49+
50+
- [ ] Run the mechanical migrator over the original `.res` (via
51+
`git show <pre-migration-sha>:path/to/file.res`) and diff its
52+
output against the hand-port.
53+
- [ ] Substitute placeholder `Json` / `Dict[String, V]` references with
54+
whatever canonical names #161 / #162 land with.
55+
- [ ] Re-narrow effect rows against the actual stdlib declarations.
56+
- [ ] Run `affinescript check src/` against every file and resolve any
57+
remaining errors that the hand-port couldn't anticipate.

bots/sustainabot/bot-integration/bindings/Deno.res

Lines changed: 0 additions & 160 deletions
This file was deleted.

bots/sustainabot/bot-integration/bindings/Deno.res.js

Lines changed: 0 additions & 39 deletions
This file was deleted.

bots/sustainabot/bot-integration/bindings/Fetch.res

Lines changed: 0 additions & 13 deletions
This file was deleted.

bots/sustainabot/bot-integration/bindings/Fetch.res.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

bots/sustainabot/bot-integration/deno.json

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,28 @@
11
{
22
"name": "@oikos/bot",
3-
"version": "0.1.1-beta",
3+
"version": "0.2.0-beta",
44
"exports": {
5-
".": "./src/Oikos.res.js",
6-
"./router": "./src/Router.res.js",
7-
"./tea": "./src/tea/ServerTea.res.js"
5+
".": "./src/Oikos.affine",
6+
"./router": "./src/Router.affine",
7+
"./tea": "./src/tea/ServerTea.affine"
88
},
99
"publish": {
10-
"include": ["src/**/*.js", "src/**/*.res", "bindings/**/*.js", "bindings/**/*.res", "rescript-runtime/**/*.js", "README.md", "LICENSE"]
10+
"include": ["src/**/*.affine", "README.md", "LICENSE", "MIGRATION-NOTES.md"]
1111
},
1212
"tasks": {
13-
"build:rescript": "rescript build",
14-
"watch:rescript": "rescript build -w",
15-
"clean": "rescript clean",
16-
"start": "deno run --allow-net --allow-env --allow-read src/Oikos.res.js",
17-
"start:legacy": "deno run --allow-net --allow-env --allow-read src/Main.res.js",
18-
"dev": "deno run --watch --allow-net --allow-env --allow-read src/Oikos.res.js",
13+
"build": "affinescript compile src/Main.affine",
14+
"watch": "affinescript compile --watch src/Main.affine",
15+
"clean": "rm -rf _build",
1916
"smee": "deno run --allow-net --allow-env scripts/smee-client.ts",
20-
"test": "deno test --allow-net --allow-env --allow-read",
21-
"lint": "deno lint",
22-
"fmt": "deno fmt"
17+
"test": "affinescript test",
18+
"lint": "affinescript lint src/",
19+
"fmt": "affinescript fmt src/"
2320
},
2421
"imports": {
2522
"@std/http": "jsr:@std/http@^1.0.0",
2623
"@std/log": "jsr:@std/log@^0.224.0",
2724
"@std/dotenv": "jsr:@std/dotenv@^0.225.0",
28-
"@std/crypto": "jsr:@std/crypto@^1.0.0",
29-
"@rescript/runtime/lib/es6/": "./rescript-runtime/"
30-
},
31-
"compilerOptions": {
32-
"strict": true,
33-
"allowJs": true
34-
},
35-
"lint": {
36-
"rules": {
37-
"tags": ["recommended"]
38-
}
25+
"@std/crypto": "jsr:@std/crypto@^1.0.0"
3926
},
4027
"fmt": {
4128
"useTabs": false,

0 commit comments

Comments
 (0)