Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 82 additions & 79 deletions BOOTSHARP-BUILD.md
Original file line number Diff line number Diff line change
@@ -1,117 +1,120 @@
# Bootsharp Local Build Process
# Bootsharp local build pipeline

Run these steps IN ORDER every time Elringus pushes upstream changes or you need a fresh local build.
This is the **only** doc for rebuilding Bootsharp locally. If anything else (CLAUDE.md, agent memory, a comment somewhere) disagrees, this file wins — open a PR to fix the other.

---

## 1. D:\bootsharp (core package)

Elringus **force-pushes** `feat/overload`. Never merge. Never stash. Always reset hard.
## TL;DR

```powershell
git -C D:\bootsharp fetch
git -C D:\bootsharp reset --hard origin/feat/overload

# Reapply the projectability patch (GlobalType.cs + TypeInspector.cs)
# Check label first — stash index shifts if GitHub Desktop adds entries:
git -C D:\bootsharp stash list
git -C D:\bootsharp stash apply stash@{N}
# Look for: "On feat/overload: !!GitHub_Desktop<feat/overload>"
pwsh ./scripts/build-bootsharp.ps1
```

Bump version in `D:\bootsharp\src\cs\Directory.Build.props`:
```xml
<Version>0.8.0-alpha.NNN</Version> <!-- increment NNN by 1 -->
```
That's the build. The script does everything: resets Bootsharp to upstream, applies the patch series under `patches/`, bumps the alpha, packs core + Bootsharp.FileSystem to their local NuGet feeds, bumps the pins in `Directory.Packages.props`, publishes `Motely.Wasm`, and runs the Node smoke tests. Green or red.

Build JS then pack C#:
```powershell
npm --prefix D:\bootsharp\src\js run build
bash D:\bootsharp\src\cs\.scripts\pack.sh # outputs to D:\bootsharp\src\cs\.nuget\
```
Run `pwsh ./scripts/build-bootsharp.ps1 -WhatIf` first if you want to see every command without executing.

Optional E2E (slow, catches regressions in the generator):
```powershell
npm --prefix D:\bootsharp\src\js run compile-test
npm --prefix D:\bootsharp\src\js run test
```
## What the script does (11 steps)

> **The patch** skips non-projectable interop members (ref structs, byref T&, delegates,
> bare IEnumerable<T>) and drops imported interfaces that have any such member.
> Lives in `Common/Global/GlobalType.cs` and `Common/Inspection/TypeInspector.cs`.
1. **Sanity-check tooling** — git, dotnet, node, npm, bash all on PATH.
2. **Reset `D:\bootsharp` to `origin/feat/spec`** — `fetch --all --prune` then `reset --hard`. Force-pushed upstream, never merge. Refuses to continue if tracked-file changes remain.
3. **Apply `patches/*.patch` in lexical order** — `git apply --check` then `git apply`. Hard failure if a patch doesn't apply — that means it's stale vs. upstream and needs hand-rebasing (which is also the cue to send Elringus a PR).
4. **Bump `<Version>` in `D:\bootsharp\src\cs\Directory.Build.props`** — increments the NNN in `0.8.0-alpha.NNN`. Override with `-AlphaBumpMode none` or `-AlphaBumpMode <explicit-version>`.
5. **Build JS, then pack C#** — `npm --prefix src/js run build`, then `bash src/cs/.scripts/pack.sh`. Output lands in `D:\bootsharp\src\cs\.nuget`.
6. **Pack Bootsharp.FileSystem** — `dotnet pack D:\extra\bootsharp\cs -c Release -o D:\extra\bootsharp\cs\.nuget`. Version is auto-generated from the current timestamp (`yyyy.MM.dd.HHmm`).
7. **Purge the NuGet user cache** for the new alpha + new FileSystem timestamp, so the consumer restore doesn't serve a stale entry.
8. **Bump pins in `Directory.Packages.props`** — XML-edit (preserves formatting) of `Bootsharp`, `Bootsharp.Common`, `Bootsharp.Inject` → new alpha and `Bootsharp.FileSystem` → new timestamp.
9. **`dotnet publish Motely.Wasm -c Release`** — produces `motely-wasm/dist`.
10. **Smoke** — `node Motely.Wasm/motely.test.mjs` and `node Motely.Wasm/getctx-wasm.test.mjs`. Skip with `-SkipSmoke`.
11. **Summary** — versions, feed paths, `RESULT: PASS`.

---
## Branch and feed setup (one-time)

## 2. D:\extra\bootsharp (Bootsharp.FileSystem — $100/mo sponsor package)
| Repo | Local path | Branch | Local feed |
|---|---|---|---|
| Bootsharp core | `D:\bootsharp` | `feat/spec` (force-pushed) | `D:\bootsharp\src\cs\.nuget` |
| Bootsharp.FileSystem (sponsor) | `D:\extra\bootsharp` | — (timestamp-versioned) | `D:\extra\bootsharp\cs\.nuget` |

Pack to local NuGet only. **Do NOT run `publish.sh`** — that pushes to the rewaffle remote feed (Elringus's job).
Register both feeds in your **user-level** `NuGet.Config` (`%APPDATA%\NuGet\NuGet.Config` on Windows). The repo's `nuget.config` deliberately omits `<clear/>` so these merge in:

```powershell
dotnet pack D:\extra\bootsharp\cs --configuration Release --output D:\extra\bootsharp\cs\.nuget
```xml
<configuration>
<packageSources>
<add key="bootsharp-local" value="D:\bootsharp\src\cs\.nuget" />
<add key="bootsharp-filesystem" value="D:\extra\bootsharp\cs\.nuget" />
</packageSources>
</configuration>
```

Version is auto-generated from the current timestamp (`yyyy.MM.dd.HHmm`).
Check the exact filename produced — you'll need it for the next step:
Override the paths if your checkouts live elsewhere:

```powershell
ls D:\extra\bootsharp\cs\.nuget\Bootsharp.FileSystem.*.nupkg
pwsh ./scripts/build-bootsharp.ps1 `
-BootsharpRoot C:\src\bootsharp `
-BootsharpFsRoot C:\src\bootsharp-filesystem
```

It resolves `Bootsharp.Common Version="*-*"` (floating) → picks up the alpha you just packed.
## Patch series

---
The series lives under `patches/` and is the canonical record of every Bootsharp delta Motely needs that hasn't landed upstream yet. Two files today:

## 3. x:\JammySeedFinder\src\MotelyJAML — update pins
### `patches/01-projectability.patch`

Edit `Directory.Packages.props` with the new versions:
```xml
<PackageVersion Include="Bootsharp" Version="0.8.0-alpha.NNN" />
<PackageVersion Include="Bootsharp.Common" Version="0.8.0-alpha.NNN" />
<PackageVersion Include="Bootsharp.Inject" Version="0.8.0-alpha.NNN" />
<PackageVersion Include="Bootsharp.FileSystem" Version="yyyy.MM.dd.HHmm" />
```
Status today: **not yet vendored** — exists as a placeholder (`patches/01-projectability.patch.PLACEHOLDER`) until the maintainer exports the local stash. Until that's done, `dotnet publish Motely.Wasm` will fail when the inspector hits a non-projectable interop member.

Touches: `src/cs/Bootsharp.Common/Global/GlobalType.cs`, `src/cs/Bootsharp.Common/Inspection/TypeInspector.cs`.

Effect: skips non-projectable interop members (ref structs, byref `T&`, delegates, bare `IEnumerable<T>`) and drops imported interfaces that have any such member.

---
Smallest test it must pass: `dotnet publish Motely.Wasm -c Release` succeeds. Failure mode without it: the publish-time inspector throws on Motely's `MotelySingleSearchContext` and friends.

## 4. Build Motely.Wasm
One-time export (run on the machine that has the stash):

```powershell
dotnet publish x:\JammySeedFinder\src\MotelyJAML\Motely.Wasm -c Release
cd D:\bootsharp
git stash list # find "On feat/spec: !!GitHub_Desktop<feat/spec>"
git stash show -p stash@{N} `
> X:\JammySeedFinder\src\MotelyJAML\patches\01-projectability.patch
# then delete patches/01-projectability.patch.PLACEHOLDER
```

Success looks like:
```
Bootsharp ES module published at x:\JammySeedFinder\src\MotelyJAML\..\motely-wasm\dist
```
### `patches/02-publish-fixes.patch`

---
Three-commit series against `Bootsharp.Publish`. Without it the package doesn't even compile against Motely's surface.

## 5. Verify
- **Commit 1** — `TypeDeclarationGenerator.cs`: migrate to the post-`6edaa2c` `SolutionInspection.Surfaces` / `.Types` split. Members now live on `InstanceMeta` (the surface), not `InstancedMeta` (the type).
- **Commit 2** — `InstanceGenerator.cs`: qualify the runtime root with `global::Bootsharp.*` everywhere in the emit template (otherwise the generated wrapper namespace `Bootsharp.Generated.Imports.Bootsharp.FileSystem` shadows the root); rename `JSImported` → `JSProxy` to match the runtime API.
- **Commit 3** — `SurfaceInspector.cs`: unwrap `Task<T>` before instance inspection. Mirrors `SerializedInspector`. Without it the inspector recurses into `Task<T>`'s public methods and emits invalid `JSConfiguredTaskAwaitable\`1` proxies.

```powershell
node x:\JammySeedFinder\src\MotelyJAML\Motely.Wasm\motely.test.mjs
node x:\JammySeedFinder\src\MotelyJAML\Motely.Wasm\pack-consumer-smoke.mjs
```
Smallest tests it must pass:

Both must exit clean.
- `dotnet build` on `D:\bootsharp\src\cs\Bootsharp.Publish` succeeds (commit 1 unblocks compile).
- The Bootsharp E2E suite (`npm --prefix src/js run compile-test`) emits no class containing a backtick in its name (commit 3).
- `dotnet publish Motely.Wasm -c Release` succeeds and `node Motely.Wasm/motely.test.mjs` exits 0 (commit 2).

---
## Troubleshooting

## NuGet cache gotcha
| Error you'll actually see | Cause | Fix |
|---|---|---|
| `CS0234: 'JSImported' does not exist in the namespace 'Bootsharp.Generated.Imports.Bootsharp'` | `patches/02-publish-fixes.patch` not applied | Re-run script; check step 3 log for the `--check` failure |
| Generated emit contains `JSConfiguredTaskAwaitable\`1` | `patches/02` partial apply (commit 3 missing) | Re-apply the whole series (delete `D:\bootsharp` working changes and re-run) |
| `Bootsharp.Common` resolves to a stale alpha | NuGet cache hit | Re-run the script (step 7 purges); or manually `Remove-Item -Recurse $env:USERPROFILE\.nuget\packages\bootsharp*` |
| `NETSDK1083: The specified RuntimeIdentifier 'browser-wasm' is not recognized` | Missing wasm-tools workload | `dotnet workload install wasm-tools` |
| `node motely.test.mjs` prints `{}` instead of populated data | Bootsharp marshaling regression (see CLAUDE.md "Interop debugging rules") | Assert shape, not just "didn't throw"; check that every `[Export]`-ed type in `Program.cs` is projectable |
| The publish-time Bootsharp inspector throws on a `ref struct` / delegate / bare `IEnumerable<T>` | `patches/01-projectability.patch` not yet vendored | Export the stash (see § Patch series) |
| `Bootsharp.FileSystem` package not found at restore | `D:\extra\bootsharp\cs\.nuget` not registered as a feed | Add it to the user-level `NuGet.Config` (see § Branch and feed setup) |

If you reuse the same version number, NuGet serves the cached old package. Purge it:
```powershell
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp\0.8.0-alpha.NNN"
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.common\0.8.0-alpha.NNN"
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.inject\0.8.0-alpha.NNN"
```
## Upstreaming

---
The maintainer sponsors Elringus at the $100 tier. When `patches/02-publish-fixes.patch` rebases cleanly against `feat/spec` HEAD and the smoke tests pass, send Elringus a PR for the three commits — the patch file's commit messages and author trailers are already in the right shape (`git am patches/02-publish-fixes.patch` will replay them). Same for `01-projectability.patch` once it's vendored.

## Local NuGet feed locations
When a patch lands upstream, delete the file from `patches/`. The script applies whatever's there — none means none.

| Package | Feed path |
|---|---|
| Bootsharp.* (core) | `D:\bootsharp\src\cs\.nuget\` |
| Bootsharp.FileSystem | `D:\extra\bootsharp\cs\.nuget\` |
## NuGet cache gotcha (already handled by step 7)

Both are registered in the user-level `NuGet.Config`.
Reusing a version number you've already restored once (e.g., you re-ran the script with `-AlphaBumpMode none`) makes NuGet serve the cached old package. The script's step 7 purges these eagerly, but if you ever hit the symptom in a manual run:

```powershell
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp\<version>"
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.common\<version>"
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.inject\<version>"
Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.filesystem\<timestamp>"
```
85 changes: 5 additions & 80 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,94 +59,19 @@ CDN (unpkg/jsdelivr) updates after `npm publish`.
- **PRNG changes invalidate every saved seed.** `MotelySingleSearchContext.*.cs` and `MotelyVectorSearchContext.*.cs` carry stream generation; any output change here breaks reproducibility against Balatro. `Motely.Tests` will catch it — run the suite before committing.
- **Generated artifacts come from the generator.** Do not hand-edit `jaml.schema.json` or `jaml-schema.cs` — they are emitted by `Motely.CLI/MotelyJAML.schema.generator.cs`. Do not hand-edit anything under `Motely.Wasm/obj/` (Bootsharp output) or `motely-wasm/` (Bootsharp publish root, gitignored).

## Bootsharp source and docs
## Bootsharp local build

motely-wasm builds against Bootsharp pinned in `Directory.Packages.props` (`Bootsharp`, `Bootsharp.Common`, `Bootsharp.Inject` — all the same version; sponsor `Bootsharp.FileSystem` is versioned separately). Read these files directly — do not rely on public Bootsharp docs:
Build pipeline — branch, patch series, version pins, troubleshooting — is documented in `BOOTSHARP-BUILD.md` and automated as one PowerShell script:

### Building Bootsharp locally

Source: `D:\bootsharp`. Branch sets the interop ABI: `feat/raw-interop` = NativeAOT-LLVM raw C-ABI (alpha.31x); older alphas use `[JSImport]`/`[JSExport]`.

**Updating to the latest push — it is NOT `git pull`.** Elringus force-pushes / rebases `feat/delegates`, so the remote history is rewritten under the same commit message (e.g. "implement delegates support" gets a new hash each push). A `git pull` sees "diverged" and would make a merge commit. Instead:

```
cd D:/bootsharp && git fetch --all --prune && git reset --hard origin/feat/delegates
```powershell
pwsh ./scripts/build-bootsharp.ps1
```

This discards the local pointer and lands directly on his rewritten commit — linear, no merge commit. (Working tree is normally clean here, so nothing is lost.)

Repack (from `D:\bootsharp\AGENTS.md`, in order):

1. Once: `bash src/cs/.scripts/llvm.sh` (downloads NativeAOT-LLVM to `src/cs/.llvm`).
2. `cd src/js && npm run build`.
3. Bump `<Version>` in `src/cs/Directory.Build.props` (only if sources changed).
4. `cd src/cs && bash .scripts/pack.sh` (packs to `src/cs/.nuget`).

**Then rebuild the sponsor FileSystem extension** — `Bootsharp.FileSystem` pins `Bootsharp.Common` as `*-*` (floats to local latest), so whenever you repack `Bootsharp.Common` you must repack FileSystem against it or the consumer restores a FileSystem built against a stale Common:

5. `dotnet pack D:/extra/bootsharp/cs/Bootsharp.FileSystem/Bootsharp.FileSystem.csproj -c Release -o D:/extra/bootsharp/cs/.nuget` (packs the C# NuGet to the extra feed). `D:/extra/bootsharp/scripts/package.sh` is the separate JS-side build — it bundles the TypeScript and runs `npm publish` of `@rewaffle/bootsharp-file-system` to the GitHub registry; it is not part of the local C# NuGet loop.

`Bootsharp.FileSystem` has no `<Version>`; it stamps a build-time timestamp `yyyy.MM.dd.HHmm` (NuGet normalizes to e.g. `2026.5.22.1237`). Read the actual emitted version from the pack log — that's the pin to use below.

Local feeds are user-level (`%APPDATA%\NuGet\NuGet.Config`), not committed: `bootsharp-local` → `D:\bootsharp\src\cs\.nuget`; `Bootsharp.FileSystem` feed → `D:\extra\bootsharp\cs\.nuget`.

Consume here: bump all three `Bootsharp*` versions in `Directory.Packages.props` together, **and** bump `Bootsharp.FileSystem` to the timestamp from step 5 (it tracks the same Common, just versioned separately). Validate with `dotnet publish Motely.Wasm -c Release` then `node Motely.Wasm/motely.test.mjs` (`RESULT: PASS`) — Bootsharp's own E2E suite passing does not prove Motely's types generate valid bindings.

**Docs:**
@D:/bootsharp/docs/guide/index.md
@D:/bootsharp/docs/guide/getting-started.md
@D:/bootsharp/docs/guide/build-config.md
@D:/bootsharp/docs/guide/sideloading.md
@D:/bootsharp/docs/guide/serialization.md
@D:/bootsharp/docs/guide/interop-modules.md
@D:/bootsharp/docs/guide/interop-instances.md
@D:/bootsharp/docs/guide/llvm.md
@D:/bootsharp/docs/guide/declarations.md
@D:/bootsharp/docs/guide/preferences.md
@D:/bootsharp/docs/guide/extensions/dependency-injection.md
@D:/bootsharp/docs/guide/extensions/file-system.md

**JS source:**
@D:/bootsharp/src/js/src/exports.mts
@D:/bootsharp/src/js/src/boot.mts
@D:/bootsharp/src/js/src/index.mts

**C# publish source:**
@D:/bootsharp/src/cs/Bootsharp.Publish/

**Sample — minimal (canonical NativeAOT-LLVM boot, no framework):**
@D:/bootsharp/samples/minimal/README.md
@D:/bootsharp/samples/minimal/cs/Minimal.csproj
@D:/bootsharp/samples/minimal/cs/Program.cs
@D:/bootsharp/samples/minimal/main.mjs
@D:/bootsharp/samples/minimal/index.html

**Sample — react (Vite + React app consuming Bootsharp ESM package):**
@D:/bootsharp/samples/react/README.md
@D:/bootsharp/samples/react/package.json
@D:/bootsharp/samples/react/vite.config.ts
@D:/bootsharp/samples/react/tsconfig.json
@D:/bootsharp/samples/react/index.html
@D:/bootsharp/samples/react/src/main.tsx
@D:/bootsharp/samples/react/src/computer.tsx
@D:/bootsharp/samples/react/src/donut.tsx
@D:/bootsharp/samples/react/backend/package.json
@D:/bootsharp/samples/react/backend/Backend.WASM/Backend.WASM.csproj
@D:/bootsharp/samples/react/backend/Backend.WASM/Program.cs
@D:/bootsharp/samples/react/backend/Backend/Backend.csproj
@D:/bootsharp/samples/react/backend/Backend/IComputer.cs
@D:/bootsharp/samples/react/backend/Backend.Prime/Backend.Prime.csproj
@D:/bootsharp/samples/react/backend/Backend.Prime/IPrimeUI.cs
@D:/bootsharp/samples/react/backend/Backend.Prime/Options.cs
@D:/bootsharp/samples/react/backend/Backend.Prime/Prime.cs

**Local patch vs upstream:**
@X:/JammySeedFinder/src/MotelyJAML/bootsharp-fixes-vs-6edaa2c.patch
That's the build. Resets `D:\bootsharp` to upstream, applies `patches/*.patch`, packs core + Bootsharp.FileSystem, bumps pins in `Directory.Packages.props`, publishes `Motely.Wasm`, runs smoke tests. If it doesn't run green, read `BOOTSHARP-BUILD.md` § Troubleshooting before improvising. Never duplicate build prose here — the script and `BOOTSHARP-BUILD.md` are the source of truth.

## Sponsor-gated features

- **`Bootsharp.FileSystem`** — The file system extension (`PickRoot`, `MountRoot`, `UnmountRoot`, `ReadTextFile`, `WriteTextFile`, `OnFileChanges`) is exclusive to [Bootsharp sponsors](https://github.com/sponsors/elringus). The NuGet package (`Bootsharp.FileSystem`) and its sample repo are not publicly available on NuGet or GitHub.
@D:/bootsharp/docs/guide/extensions/file-system.md

## Things that look weird but aren't

Expand Down
Loading
Loading