@mulmoclaude/core 4.0.0 → 4.0.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.
@@ -800,40 +800,77 @@ shipped builders produce, and asserts `handlePermission` comes back over the MCP
800
800
 
801
801
  ### Cause
802
802
 
803
- `Dockerfile.sandbox` installs the CLI unpinned (`RUN npm install -g @anthropic-ai/claude-code
804
- tsx`), so the image freezes whatever was latest when it was built. Two mechanisms then keep it
805
- frozen:
803
+ The image freezes whichever CLI was current when it was built, and
804
+ `ensureSandboxImage()` (`server/system/docker.ts`) rebuilds only when the **Dockerfile's SHA**
805
+ changes. A new CLI release upstream doesn't change that SHA, so nothing retriggers the build.
806
806
 
807
- 1. `ensureSandboxImage()` (`server/system/docker.ts`) rebuilds only when the **Dockerfile's
808
- SHA** changes. A new CLI release upstream doesn't change that SHA, so nothing retriggers.
809
- 2. Deleting the image does not delete the **build cache**. The rebuild reuses the cached
810
- `npm install -g` layer (it reports `CACHED` in 0.0s) and reinstalls nothing.
807
+ ### Fix
811
808
 
812
- So the usual "remove it and let it rebuild" reflex genuinely does nothing here, which is why
813
- this one burns time.
809
+ Read it off the boot log — since #2842 the server records the version at build time as an image
810
+ label and prints it on every start, so no container has to be run to find out:
814
811
 
815
- ### Fix
812
+ ```
813
+ INFO [sandbox] sandbox image claudeCodeVersion=2.1.220 ageDays=3
814
+ ```
816
815
 
817
- Check the version inside the image — the host's `claude --version` says nothing about it, and
818
- the entrypoint override is required because the image's ENTRYPOINT is the sandbox script:
816
+ `claudeCodeVersion=unrecorded` means the image predates the label (or was built with npm
817
+ unreachable). In that case ask the image directly — the entrypoint override is required because
818
+ the image's ENTRYPOINT is the sandbox script, and the host's own `claude --version` says nothing
819
+ about what is inside:
819
820
 
820
821
  ```bash
821
822
  docker run --rm --entrypoint claude mulmoclaude-sandbox --version
822
823
  ```
823
824
 
824
- If it's behind, drop the image AND the build cache, then let the next run rebuild:
825
+ If it's behind, drop the image and let the next run rebuild:
825
826
 
826
827
  ```bash
827
828
  yarn sandbox:remove # docker rmi mulmoclaude-sandbox
828
- docker builder prune -a -f # the step that actually invalidates the npm layer
829
829
  ```
830
830
 
831
- `docker builder prune -a -f` clears the builder cache for the whole daemon, not just this
832
- image, so unrelated builds are slower once afterwards. That is the cost of the fix, not a
833
- sign something went wrong.
831
+ Two warns fire on their own when this is worth acting on: `sandbox image is stale` past 30 days,
832
+ and `Claude CLI in the sandbox image is older than the version our MCP config needs` below
833
+ 2.1.121 (the floor for `alwaysLoad`).
834
+
835
+ > **Older than #2842?** Back then the rebuild reused the cached `npm install -g` layer (reported
836
+ > `CACHED` in 0.0s) and reinstalled nothing, so `yarn sandbox:remove` alone genuinely did nothing
837
+ > and `docker builder prune -a -f` was needed. The Dockerfile now installs an exact
838
+ > `@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}` resolved on the host, so a moved CLI changes
839
+ > the layer's own command string and invalidates it. Don't reach for `builder prune` first — it
840
+ > clears the cache for the whole daemon.
841
+
842
+ The CLI is deliberately left unpinned by default (#2202), so this can recur whenever an upstream
843
+ fix matters to you — the log line above is the way to rule it in or out.
844
+
845
+ ## A turn dies on `handlePermission not found` — read the broker lines before anything else
846
+
847
+ ### Symptoms
848
+
849
+ The same `MCP tool mcp__mulmoclaude__handlePermission ... not found` as the three sections
850
+ above, and you can't yet tell WHICH of them you are in.
851
+
852
+ ### Cause
853
+
854
+ They are genuinely different failures — a permanent load failure, a startup race, a frozen CLI —
855
+ and guessing between them is what makes this expensive. Since #2842 the log answers it directly,
856
+ so read these three before forming a theory:
857
+
858
+ | Log line | What it tells you |
859
+ |---|---|
860
+ | `spawning agent … broker=tsx` | This install is on the SLOW path: the bundle is missing, so the broker is transcoded from source on every spawn (seconds to tens of seconds over a Windows/macOS bind mount). A `broker bundle missing` warn accompanies it once per process. |
861
+ | `[mcp] broker ready bootMs=… initializeMs=…` | The broker DID connect, and how long it took. `broker cold boot is slow` replaces it past 5 s. |
862
+ | `brokerEverReady=false` on the retry warn | No beacon ever arrived for that chat — the broker did not come up at all, so the automatic 3 s replay will reproduce the same error and only double the wait. |
863
+
864
+ ### Fix
834
865
 
835
- The CLI is deliberately left unpinned (#2202), so this can recur whenever an upstream fix
836
- matters to you — the check above is the way to rule it in or out.
866
+ - `broker=tsx` → this is the cold-boot cost, not the connect-wait ceiling. In a dev checkout run
867
+ `yarn build:mcp-broker` (or plain `yarn build`); on an npm install, update `mulmoclaude` —
868
+ published launchers have shipped the bundle since 1.9.0.
869
+ - `broker ready` present with a small `initializeMs`, failing anyway → it is the startup race,
870
+ not the boot. See the scheduled-run section above.
871
+ - `brokerEverReady=false` with no `broker ready` line anywhere → the broker never started. That
872
+ is the permanent load failure; check the `Cannot find module` section.
873
+ - Old or unrecorded `claudeCodeVersion` alongside any of these → rule out the frozen CLI first.
837
874
 
838
875
  ---
839
876
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mulmoclaude/core",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "Shared server-side core for MulmoClaude and MulmoTerminal — the always-shipped-together subsystems consolidated behind subpath exports so the two hosts can't drift. Server-only except the browser-safe ./artifacts, ./whisper/client, ./workspace-setup/slug, ./translation/client, ./remote-view, ./remote-host and ./plugin-vue entries. All host specifics are injected.",
5
5
  "repository": {
6
6
  "type": "git",