instar 1.3.104 → 1.3.105
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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +14 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.js +6 -1
- package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
- package/dist/scheduler/MentorOnboardingTick.d.ts +7 -0
- package/dist/scheduler/MentorOnboardingTick.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingTick.js +8 -3
- package/dist/scheduler/MentorOnboardingTick.js.map +1 -1
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +16 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.3.105.md +64 -0
- package/upgrades/side-effects/mentor-stage-a-robustness.md +57 -0
- package/upgrades/side-effects/mesh-signing-key-filename-fix.md +54 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Side-effects review — Mentor Stage-A: surface error + harden spawn
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/MENTOR-STAGE-A-ROBUSTNESS-SPEC.md`
|
|
4
|
+
**Changes:** `src/scheduler/MentorOnboardingTick.ts`, `src/scheduler/MentorOnboardingRunner.ts`, `src/server/AgentServer.ts` (+ unit test)
|
|
5
|
+
**Class:** mentor reliability + diagnosability fix.
|
|
6
|
+
|
|
7
|
+
## What changed
|
|
8
|
+
|
|
9
|
+
1. `MentorTickResult` gains `error?: string`.
|
|
10
|
+
2. `runMentorTick`'s bare `catch {}` around `spawnStageA` → `catch (err)` that
|
|
11
|
+
captures the message into the returned result (`{…, error}`) + the finding
|
|
12
|
+
title.
|
|
13
|
+
3. `MentorOnboardingRunner.startTick().catch` adds the same `error` field (for a
|
|
14
|
+
rejected `tick()`).
|
|
15
|
+
4. `spawnStageA` (AgentServer.ts) wraps `spawnSession` in a single retry with a
|
|
16
|
+
3s backoff; on persistent failure throws `stage-a-spawn-failed: … — <cause>`.
|
|
17
|
+
|
|
18
|
+
## Blast radius
|
|
19
|
+
|
|
20
|
+
- **`/mentor/status` consumers:** purely additive — `lastResult` may now include
|
|
21
|
+
an `error` string on the failure path. No field removed/renamed.
|
|
22
|
+
- **Healthy mentor ticks:** unchanged — new code runs only on the catch/failure
|
|
23
|
+
path or a throwing spawn.
|
|
24
|
+
- **Stage-A two-hats isolation:** unchanged — still spawns with the empty
|
|
25
|
+
`STAGE_A_ALLOWED_TOOLS` grant; only error handling + a retry added.
|
|
26
|
+
- **Public API / DB schema / config:** none changed. No new route (the
|
|
27
|
+
AgentServer change is inside an existing closure — E2E-PAIRING exempt).
|
|
28
|
+
|
|
29
|
+
## What could break (and why it doesn't)
|
|
30
|
+
|
|
31
|
+
- **The retry doubling spawn load?** Only on a spawn that already failed once,
|
|
32
|
+
and capped at 2 attempts with a 3s gap — negligible, and only on the
|
|
33
|
+
already-failing path.
|
|
34
|
+
- **`error` field typing:** flows through `MentorRunResult extends
|
|
35
|
+
Omit<MentorTickResult,'reason'>` which keeps `error?`. `tsc` clean.
|
|
36
|
+
- **Masking a persistent failure:** no — a persistent failure still throws after
|
|
37
|
+
2 attempts, now with the cause in the message.
|
|
38
|
+
|
|
39
|
+
## Security
|
|
40
|
+
|
|
41
|
+
No new external input / network / auth / fs surface. The surfaced `error` is an
|
|
42
|
+
internal spawn/timeout message (no secrets).
|
|
43
|
+
|
|
44
|
+
## Migration parity
|
|
45
|
+
|
|
46
|
+
Server-internal scheduler/server code — every agent gets it by running the new
|
|
47
|
+
build. No PostUpdateMigrator entry required.
|
|
48
|
+
|
|
49
|
+
## Rollback
|
|
50
|
+
|
|
51
|
+
Revert the commit. No persisted state, schema, or API contract affected.
|
|
52
|
+
|
|
53
|
+
## Tests
|
|
54
|
+
|
|
55
|
+
`tests/unit/MentorOnboardingRunner.test.ts` (+1): a throwing `spawnStageA` now
|
|
56
|
+
surfaces `lastResult.error` with the real message (was swallowed). Full
|
|
57
|
+
mentor/stage suite — 113 tests across 9 files — green; `tsc --noEmit` clean.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Side-effects review — mesh signing-key filename fix (the SEND-side break)
|
|
2
|
+
|
|
3
|
+
## What was happening (real-hardware, 2026-05-30)
|
|
4
|
+
|
|
5
|
+
After the /mesh/rpc auth exemption (v1.3.104) deployed to BOTH machines, the Mac
|
|
6
|
+
mini STILL showed offline on the laptop (the router). The mini→laptop presence
|
|
7
|
+
pull worked (the mini's log: `recorded 1 peer(s) online: m_cc2ec651`), but the
|
|
8
|
+
laptop→mini direction never fired and the mini never even RECEIVED the laptop's
|
|
9
|
+
`session-status` call.
|
|
10
|
+
|
|
11
|
+
Root cause: the server-boot loader for `localSigningKeyPem` — the private key the
|
|
12
|
+
`MeshRpcClient` signs every outbound machine-to-machine command with — hard-coded
|
|
13
|
+
the filename `signing-private.pem`. But `MachineIdentity` writes the signing key
|
|
14
|
+
as `signing-key.pem` (its `SIGNING_KEY_FILE`). So a normally-created install had
|
|
15
|
+
`signing-private.pem` ABSENT → `localSigningKeyPem` stayed `''` → the
|
|
16
|
+
`MeshRpcClient` signed with an empty key → the send threw → the machine could NOT
|
|
17
|
+
pull presence from / deliver to / transfer to any peer. It still RECEIVED fine,
|
|
18
|
+
because the receive path verifies the OTHER machine's key (which it has), not its
|
|
19
|
+
own. That produced the exact asymmetry observed: the mini (propagated with the
|
|
20
|
+
non-canonical `signing-private.pem`) could send; the laptop (canonical
|
|
21
|
+
`signing-key.pem`) could not — two filename bugs lining up.
|
|
22
|
+
|
|
23
|
+
Confirmed by giving the laptop a `signing-private.pem` copy of its own key +
|
|
24
|
+
restarting: the laptop immediately began recording the mini online over HTTP, and
|
|
25
|
+
the pool showed both machines online.
|
|
26
|
+
|
|
27
|
+
## The fix
|
|
28
|
+
|
|
29
|
+
- **`src/commands/server.ts`** — the loader now reads the CANONICAL
|
|
30
|
+
`signing-key.pem` first, falling back to the legacy/propagated
|
|
31
|
+
`signing-private.pem`, so BOTH layouts load a key. (The lease transport already
|
|
32
|
+
used `idMgr.loadSigningKey()`, which reads the canonical name — only this
|
|
33
|
+
MeshRpcClient loader was on the wrong filename.)
|
|
34
|
+
|
|
35
|
+
## Blast radius
|
|
36
|
+
|
|
37
|
+
- **Pure fix to a boot-time read on the multi-machine path.** A single-machine
|
|
38
|
+
agent never constructs a MeshRpcClient, so it is unaffected. A machine that
|
|
39
|
+
already had `signing-private.pem` (propagated) keeps working via the fallback.
|
|
40
|
+
A machine with the canonical `signing-key.pem` (the common case) now loads its
|
|
41
|
+
key and can SEND cross-machine commands — the bug fix.
|
|
42
|
+
- **No new config / route / schema / hook / skill → no migration.** Server code;
|
|
43
|
+
existing agents pick it up on the next release. This is the SEND-side companion
|
|
44
|
+
to the /mesh/rpc auth exemption (the receive-side fix) — both were needed for
|
|
45
|
+
the cross-machine pool to function over the wire.
|
|
46
|
+
- **Separately, the propagation path should write the canonical `signing-key.pem`**
|
|
47
|
+
(it currently writes `signing-private.pem`); that is a propagation-side cleanup
|
|
48
|
+
tracked separately. This fix makes the loader tolerant of both regardless.
|
|
49
|
+
|
|
50
|
+
## Tests
|
|
51
|
+
|
|
52
|
+
- `tests/unit/mesh-signing-key-resolution.test.ts` — the loader reads the
|
|
53
|
+
canonical `signing-key.pem`, tries it BEFORE the legacy `signing-private.pem`
|
|
54
|
+
(fallback order), and the canonical name matches `MachineIdentity.SIGNING_KEY_FILE`.
|