Skip to content

Commit 40cec8c

Browse files
Coordinate workspace launcher port allocation
1 parent 06d1e14 commit 40cec8c

20 files changed

Lines changed: 845 additions & 4 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ If you want the fuller workspace path after that:
8989
- Use [docs/20-ai-context-side-load.md](docs/20-ai-context-side-load.md) for the generated AI side-load contract and the `generate-context-cache.sh` workflow.
9090
- Use [docs/09-new-repo-baseline.md](docs/09-new-repo-baseline.md) when adding or onboarding a repo.
9191

92-
Repo-specific launchers can also live under `tools/local/commands/`. For example, `tools/local/commands/Run Knowledge Palace UI.command` starts the Knowledge Palace local web UI from the workspace root.
92+
Repo-specific launchers can also live under `tools/local/commands/`. Those workspace launchers should keep the host on `127.0.0.1`, prefer a repo-specific port range, and step to the next free port instead of randomizing the address. For example, `tools/local/commands/Run Knowledge Palace UI.command` starts the Knowledge Palace local web UI from the workspace root.
9393

9494
## How To Contribute
9595

docs/09-new-repo-baseline.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This is not meant to force every repo into one shape. The goal is to keep each r
1111
- Use shared caches under workspace `cache/` where that helps, but keep installs local to the repo.
1212
- Do not make a reverse-proxy or mapped-host layer mandatory unless the repo genuinely needs that behaviour.
1313
- Prefer the repo's native runtime and package manager.
14+
- For workspace launchers, keep the host stable on `127.0.0.1` and prefer a repo-specific port range that can step to the next open port instead of randomizing addresses.
1415

1516
## Default runtime expectations
1617

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 2026-04-17
44

5+
- Added `tools/scripts/workspace-port-allocator.sh` and rewired the workspace-level launchers under `tools/local/commands/` to reserve ports through `cache/runtime/ports/`, reducing same-time launcher collisions while keeping hosts fixed on `127.0.0.1` and falling forward to the next open port in each repo's range.
56
- Installed `httrack` for this workspace environment and added `tools/scripts/capture-site-reference.sh` as the repo-intake wrapper for public-site reference copies, with dry-run-by-default behavior, conservative same-domain defaults, and repo-local capture notes under `ref/httrack/`.
67
- Updated the public repo-intake surfaces in [README](../README.md), [docs/README](README.md), [09-new-repo-baseline](09-new-repo-baseline.md), and [tools/templates/repo-docs/README.site-reference.template.md](../tools/templates/repo-docs/README.site-reference.template.md) so site-reference repos have one documented `httrack` path.
78

docs/HANDOVER.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ The workspace foundation is in place and released as a stable baseline:
6565
- MemPalace is now integrated as the first core workspace service under `tools/mempalace` with user-scoped durable state under `shared/mempalace/<user>/`
6666
- installable abilities and core services are now tracked in `tools/manifests/workspace-capabilities.json`
6767
- optional abilities live under `repos/abilities/` rather than the normal repo-group update path
68+
- workspace-level launchers under `tools/local/commands/` now coordinate port reservations through `cache/runtime/ports/`, so concurrent launches keep `127.0.0.1` stable and step forward inside each repo's local port range instead of racing on the same candidate port
6869

6970
## Current source taxonomy
7071

@@ -146,6 +147,18 @@ The tracked helper surfaces for this flow now live at:
146147
- `tools/scripts/capture-site-reference.sh`
147148
- `tools/templates/repo-docs/README.site-reference.template.md`
148149

150+
## Launcher port allocation note (2026-04-17)
151+
152+
The workspace launcher baseline is now:
153+
154+
- keep local launcher hosts on `127.0.0.1`
155+
- prefer a repo-specific port range over a random address
156+
- reserve ports through `tools/scripts/workspace-port-allocator.sh`
157+
- store transient reservations under `cache/runtime/ports/`
158+
- let launchers move to the next open port, or the next open web/api pair for Workspace Hub
159+
160+
This is intended to reduce same-time launcher collisions without making local URLs unpredictable.
161+
149162
## Release verification status
150163

151164
The stable release gate has already been exercised successfully:

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Useful maintenance scripts:
8787
- `tools/scripts/manage-workspace-capabilities.sh` lists, installs, updates, enables, disables, or uninstalls tracked workspace abilities and core services, with dry-run mode by default.
8888
- `tools/scripts/update-github-refs.sh` remains the compatibility wrapper for update-only reviewed GitHub-ref flows and delegates to the capability lifecycle command.
8989
- `tools/scripts/capture-site-reference.sh` previews or runs an `httrack` capture for a public-site reference repo, using conservative same-domain defaults and writing capture notes under repo-local `ref/httrack/`.
90+
- `tools/scripts/workspace-port-allocator.sh` centralizes workspace launcher port reservations under `cache/runtime/ports/`, so concurrent launchers can keep `127.0.0.1` stable and step to the next open port without colliding.
9091
- `tools/scripts/use-design-md.sh` mirrors the managed VoltAgent `DESIGN.md` catalog ability into `cache/design-md/catalog/`, lists available site ids, and can copy a selected `DESIGN.md` into a repo root.
9192
- `tools/scripts/sync-reference-snapshots.sh` previews or refreshes ignored upstream reference snapshots under `tools/ref/`, with dry-run mode by default.
9293
- `tools/scripts/sync-codex-skills.sh` previews or syncs tracked workspace skill sources into repo `.codex/skills/` folders plus optional `.agents/skills/` compatibility mirrors, with dry-run mode by default.

repos/workspace-hub/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ pnpm build
172172
pnpm preview
173173
```
174174

175+
Workspace-level local launcher:
176+
177+
```bash
178+
tools/local/commands/Run\ Workspace\ Hub.command
179+
```
180+
181+
That launcher keeps the host on `127.0.0.1`, chooses the next free web and API port pair in the configured range, and opens the browser once the app responds.
182+
175183
To generate the workspace-side AI summaries that the repo-details panel can inspect, run from the workspace root:
176184

177185
```bash

repos/workspace-hub/vite.config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { defineConfig } from 'vite'
22
import react from '@vitejs/plugin-react'
33

4+
const apiPort = Number(process.env.WORKSPACE_HUB_API_PORT ?? '4101')
5+
46
// https://vite.dev/config/
57
export default defineConfig({
68
plugins: [react()],
@@ -9,7 +11,7 @@ export default defineConfig({
911
port: 4100,
1012
strictPort: true,
1113
proxy: {
12-
'/api': 'http://127.0.0.1:4101',
14+
'/api': `http://127.0.0.1:${apiPort}`,
1315
},
1416
},
1517
preview: {

tools/local/commands/Run Knowledge Palace UI.command

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ set -euo pipefail
55
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
66
WORKSPACE_ROOT="$(cd -- "$SCRIPT_DIR/../../.." && pwd)"
77
PROJECT_DIR="$WORKSPACE_ROOT/repos/current-builds/knowledge-palace"
8-
URL="${KNOWLEDGE_PALACE_UI_URL:-http://127.0.0.1:8765}"
8+
HOST="127.0.0.1"
9+
START_PORT="${KNOWLEDGE_PALACE_UI_PORT:-8765}"
10+
MAX_PORT="${KNOWLEDGE_PALACE_UI_MAX_PORT:-8799}"
911

1012
if [[ ! -d "$PROJECT_DIR" ]]; then
1113
echo "Knowledge Palace repo not found:"
@@ -16,6 +18,7 @@ if [[ ! -d "$PROJECT_DIR" ]]; then
1618
fi
1719

1820
cd "$PROJECT_DIR"
21+
source "$WORKSPACE_ROOT/tools/scripts/workspace-port-allocator.sh"
1922

2023
if ! python3 - <<'PY' >/dev/null 2>&1
2124
import importlib
@@ -30,16 +33,24 @@ then
3033
echo
3134
fi
3235

36+
PORT="$(workspace_reserve_port "$START_PORT" "$MAX_PORT")" || {
37+
echo "No free port found between $START_PORT and $MAX_PORT."
38+
exit 1
39+
}
40+
41+
URL="http://${HOST}:${PORT}/"
42+
3343
echo "Starting Knowledge Palace UI"
3444
echo "Project dir: $PROJECT_DIR"
3545
echo "URL: $URL"
3646
echo
3747

38-
python3 -m knowledge_palace.cli serve-ui &
48+
python3 -m knowledge_palace.cli serve-ui --host "$HOST" --port "$PORT" &
3949
SERVER_PID=$!
4050

4151
cleanup() {
4252
kill "$SERVER_PID" 2>/dev/null || true
53+
workspace_release_port_reservations || true
4354
}
4455

4556
trap cleanup EXIT INT TERM
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/zsh
2+
3+
set -euo pipefail
4+
5+
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
6+
WORKSPACE_ROOT="$(cd -- "$SCRIPT_DIR/../../.." && pwd)"
7+
PROJECT_DIR="$WORKSPACE_ROOT/repos/prototypes/THREE.MeshLine"
8+
HOST="127.0.0.1"
9+
START_PORT="${THREE_MESHLINE_PORT:-4176}"
10+
MAX_PORT="${THREE_MESHLINE_MAX_PORT:-4199}"
11+
12+
if [[ ! -d "$PROJECT_DIR" ]]; then
13+
echo "Project not found:"
14+
echo " $PROJECT_DIR"
15+
echo
16+
read '?Press Return to close this window...'
17+
exit 1
18+
fi
19+
20+
cd "$PROJECT_DIR"
21+
source "$WORKSPACE_ROOT/tools/scripts/workspace-port-allocator.sh"
22+
23+
PORT="$(workspace_reserve_port "$START_PORT" "$MAX_PORT")" || {
24+
echo "No free port found between $START_PORT and $MAX_PORT."
25+
exit 1
26+
}
27+
28+
URL="http://${HOST}:${PORT}/demo/index.html"
29+
30+
python3 -m http.server "$PORT" --bind "$HOST" &
31+
SERVER_PID=$!
32+
33+
cleanup() {
34+
kill "$SERVER_PID" 2>/dev/null || true
35+
workspace_release_port_reservations || true
36+
}
37+
38+
trap cleanup EXIT INT TERM
39+
40+
until curl -sSf "$URL" >/dev/null 2>&1; do
41+
if ! kill -0 "$SERVER_PID" >/dev/null 2>&1; then
42+
wait "$SERVER_PID"
43+
exit $?
44+
fi
45+
sleep 1
46+
done
47+
48+
open "$URL"
49+
wait "$SERVER_PID"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/zsh
2+
3+
set -euo pipefail
4+
5+
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
6+
WORKSPACE_ROOT="$(cd -- "$SCRIPT_DIR/../../.." && pwd)"
7+
PROJECT_DIR="$WORKSPACE_ROOT/repos/prototypes/Twisted-Colorful-Spheres-WebGLBlobs"
8+
HOST="127.0.0.1"
9+
START_PORT="${WEBGLBLOBS_PORT:-4176}"
10+
MAX_PORT="${WEBGLBLOBS_MAX_PORT:-4199}"
11+
12+
if [[ ! -d "$PROJECT_DIR" ]]; then
13+
echo "Project not found:"
14+
echo " $PROJECT_DIR"
15+
echo
16+
read '?Press Return to close this window...'
17+
exit 1
18+
fi
19+
20+
cd "$PROJECT_DIR"
21+
source "$WORKSPACE_ROOT/tools/scripts/workspace-port-allocator.sh"
22+
23+
PORT="$(workspace_reserve_port "$START_PORT" "$MAX_PORT")" || {
24+
echo "No free port found between $START_PORT and $MAX_PORT."
25+
exit 1
26+
}
27+
28+
URL="http://${HOST}:${PORT}/"
29+
30+
npm start -- --port "$PORT" &
31+
SERVER_PID=$!
32+
33+
cleanup() {
34+
kill "$SERVER_PID" 2>/dev/null || true
35+
workspace_release_port_reservations || true
36+
}
37+
38+
trap cleanup EXIT INT TERM
39+
40+
until curl -sSf "$URL" >/dev/null 2>&1; do
41+
if ! kill -0 "$SERVER_PID" >/dev/null 2>&1; then
42+
wait "$SERVER_PID"
43+
exit $?
44+
fi
45+
sleep 1
46+
done
47+
48+
open "$URL"
49+
wait "$SERVER_PID"

0 commit comments

Comments
 (0)