instar 1.3.196 → 1.3.198
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 +12 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +16 -1
- package/dist/commands/setup.js.map +1 -1
- package/dist/core/AgentRegistry.d.ts +15 -0
- package/dist/core/AgentRegistry.d.ts.map +1 -1
- package/dist/core/AgentRegistry.js +26 -2
- package/dist/core/AgentRegistry.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +6 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/package.json +1 -1
- package/scripts/validate-retro-harvest.mjs +272 -0
- package/src/data/builtin-manifest.json +18 -18
- package/upgrades/1.3.197.md +24 -0
- package/upgrades/1.3.198.md +24 -0
- package/upgrades/side-effects/APPRENTICESHIP-STEP0-RETRO-HARVEST-SPEC.md +78 -0
- package/upgrades/side-effects/fix-bootwrapper-install-path.md +83 -0
- package/upgrades/side-effects/fix-fetch-blocked-ports.md +74 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Side-Effects Review — Skip WHATWG fetch-blocked ports in agent port allocation
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `fix-fetch-blocked-ports`
|
|
4
|
+
**Date:** `2026-06-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Tier:** 1 (small, low-risk; ELI16 + side-effects, no converged spec)
|
|
7
|
+
**Parent principle:** Cross-Machine Coherence — One Agent, Robust Under Degraded Conditions
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
Instar's multi-machine mesh does ALL cross-machine I/O over node's global `fetch`
|
|
12
|
+
(pairing `POST /api/pair`, lease broadcast/pull, heartbeat). Node's `fetch` (undici)
|
|
13
|
+
throws `TypeError: fetch failed { cause: 'bad port' }` for any URL whose port is on the
|
|
14
|
+
WHATWG Fetch spec "bad ports" list. The default agent port-allocation range (4040–4099)
|
|
15
|
+
**contains 4045** (NFS `lockd`, a blocked port), so the allocator could hand an agent a
|
|
16
|
+
port on which it can **never** be reached over the mesh — silently, because `curl`
|
|
17
|
+
ignores the blocklist so the endpoint looks healthy.
|
|
18
|
+
|
|
19
|
+
**Observed live (2026-06-02):** a freshly-paired throwaway test agent landed on 4045 and
|
|
20
|
+
could not be joined — `instar join` failed with "fetch failed" despite `curl` to the same
|
|
21
|
+
`/api/pair` returning 400. Moving it off 4045 fixed the join instantly.
|
|
22
|
+
|
|
23
|
+
### What changed
|
|
24
|
+
- `src/core/AgentRegistry.ts`: added `FETCH_BLOCKED_PORTS` (the WHATWG bad-ports set) +
|
|
25
|
+
exported `isFetchBlockedPort(port)`. Both `allocatePort` and `allocatePortByName` now
|
|
26
|
+
skip blocked ports (in addition to used + lsof-busy ones).
|
|
27
|
+
- `src/commands/server.ts`: an unconditional startup warning when `config.port` is a
|
|
28
|
+
blocked port — the migration-parity path for EXISTING agents already on one (the
|
|
29
|
+
allocator guard only protects newly-allocated agents).
|
|
30
|
+
|
|
31
|
+
## Decision-point inventory
|
|
32
|
+
- allocator: skip vs allocate a port → skip if on the blocklist (the check precedes the
|
|
33
|
+
lsof probe, so it's deterministic).
|
|
34
|
+
- startup: warn vs silent → warn (loud, non-fatal) when an existing config sits on a
|
|
35
|
+
blocked port; we do NOT auto-re-port (that would change a running agent's port — left
|
|
36
|
+
to the operator).
|
|
37
|
+
|
|
38
|
+
## 1. Over-correction risk
|
|
39
|
+
The blocklist is the fixed WHATWG set; legitimate agent ports (4040–4044, 4046–4099, etc.)
|
|
40
|
+
are unaffected. Only 4045 falls in the default range. Skipping reduces the usable range by
|
|
41
|
+
one port — negligible (60→59).
|
|
42
|
+
|
|
43
|
+
## 2. Under-correction risk
|
|
44
|
+
Existing agents already on a blocked port aren't auto-fixed (that would change their port);
|
|
45
|
+
the startup warning surfaces it so the operator re-ports. Acceptable — auto-re-porting a
|
|
46
|
+
live agent is riskier than a loud warning.
|
|
47
|
+
|
|
48
|
+
## 3. Level-of-abstraction fit
|
|
49
|
+
The skip lives in the single port allocator both callers use; the warning at the single
|
|
50
|
+
server-start path. No scattering.
|
|
51
|
+
|
|
52
|
+
## 4. Signal vs Authority
|
|
53
|
+
Pure deterministic check against a fixed spec list — no LLM, no heuristic. Appropriate.
|
|
54
|
+
|
|
55
|
+
## 5. External surfaces
|
|
56
|
+
None. No route/config-schema change. `isFetchBlockedPort` is a new pure export.
|
|
57
|
+
|
|
58
|
+
## 6. Interactions with existing primitives
|
|
59
|
+
The allocator's existing used-port + lsof checks are unchanged; the blocklist is an
|
|
60
|
+
additional AND condition. The warning composes with the existing startup logs.
|
|
61
|
+
|
|
62
|
+
## 7. Rollback cost
|
|
63
|
+
Trivial: remove the `&& !FETCH_BLOCKED_PORTS.has(port)` clauses + the warning. No state.
|
|
64
|
+
|
|
65
|
+
## Migration parity
|
|
66
|
+
- New agents: allocator skips blocked ports (no action needed).
|
|
67
|
+
- Existing agents on a blocked port: the startup warning surfaces it (operator re-ports).
|
|
68
|
+
- Pure code; reaches existing agents on the normal dist update. No config/hook migration.
|
|
69
|
+
|
|
70
|
+
## Tests
|
|
71
|
+
`tsc --noEmit` clean. 34 `agent-registry` unit tests green, including 3 new: `isFetchBlockedPort`
|
|
72
|
+
both sides of the boundary (4045/6000/6697/2049 blocked; 4040/4046/4050/4099 not),
|
|
73
|
+
`allocatePort` throws rather than return a sole blocked candidate, and `allocatePort` skips
|
|
74
|
+
a blocked port to return the next usable one.
|