Unify frontend dev entrypoints with managed runtime

This commit is contained in:
rcourtman 2026-03-24 14:57:12 +00:00
parent 4e30822fc0
commit 6e8ab4cd64
6 changed files with 85 additions and 7 deletions

View file

@ -39,10 +39,14 @@ cd ..
### Hot Reload Dev Loop
```bash
./scripts/hot-dev.sh # Backend on :7656, frontend on :7655
npm run dev # Frontend shell on :5173, backend on :7655
npm run mock:on # Optional: enable mock data
```
Use `http://127.0.0.1:5173` in the browser for local frontend development. The
frontend dev shell proxies `/api` and `/ws` to the backend on `:7655`; do not
switch your browser to `:7655` unless you are debugging the backend directly.
Backend-only hot reload (requires `air`):
```bash
@ -74,7 +78,10 @@ examples where possible.
## Frontend Workflow
- Dev server: `cd frontend-modern && npm run dev`
- Managed dev runtime: `npm run dev`
- Runtime status: `npm run dev:status`
- Browser recovery proof: `npm run dev:verify`
- Frontend-only escape hatch: `cd frontend-modern && npm run dev:frontend-only`
- Tests: `npm run test`
- Lint: `npm run lint`
- Format: `npm run format`

View file

@ -33,6 +33,8 @@ server-side update execution surfaces.
11. `scripts/hot-dev-bg.sh`
12. `tests/integration/scripts/managed-dev-runtime.mjs`
13. `package.json`
14. `frontend-modern/package.json`
15. `scripts/dev-check.sh`
## Shared Boundaries
@ -47,7 +49,7 @@ server-side update execution surfaces.
2. Add or change release-build metadata injection, release artifact assembly, or governed promotion metadata resolution through `scripts/build-release.sh`, `scripts/release_ldflags.sh`, and `scripts/release_control/resolve_release_promotion.py`, plus the container Dockerfile and governed release workflows that consume those same contracts
3. Add or change shell installer, Windows installer, container-agent installer, or auto-update script behavior through `scripts/install.sh`, `scripts/install.ps1`, `scripts/install-container-agent.sh`, and `scripts/pulse-auto-update.sh`
4. Add or change server update transport through `internal/api/updates.go` and `frontend-modern/src/api/updates.ts`
5. Add or change local dev-runtime orchestration, managed ownership, browser-runtime proof wiring, frontend/backend coherence diagnostics, or the canonical root dev-entry wrappers through `scripts/hot-dev.sh`, `scripts/hot-dev-bg.sh`, `tests/integration/scripts/managed-dev-runtime.mjs`, and `package.json`
5. Add or change local dev-runtime orchestration, managed ownership, browser-runtime proof wiring, frontend/backend coherence diagnostics, or the canonical developer entry wrappers through `scripts/hot-dev.sh`, `scripts/hot-dev-bg.sh`, `tests/integration/scripts/managed-dev-runtime.mjs`, `package.json`, `frontend-modern/package.json`, and `scripts/dev-check.sh`
## Forbidden Paths
@ -174,6 +176,13 @@ local dev path, including explicit status, log, stop, backend-restart, and
verification wrappers, instead of requiring developers to remember
lane-specific shell paths or continue discovering the runtime through a stale
unmanaged `5173` process by accident.
That same canonical dev-entry boundary also includes the frontend workspace
package and developer health helper. `frontend-modern/package.json` may not
advertise raw `vite` as the default `dev` command, and `scripts/dev-check.sh`
must route operators back to the managed runtime entrypoint before falling back
to process-killing folklore, otherwise the repo keeps reintroducing the same
split-ownership `5173` versus `7655` confusion through secondary entry
surfaces.
That shared `scripts/install.sh` boundary must also keep one canonical service
argument builder for the runtime flags it persists. Token-bearing install
paths, token-file systemd paths, wrapper-script launches, and later service

View file

@ -853,6 +853,8 @@
"owned_files": [
"frontend-modern/src/api/ai.ts",
"frontend-modern/src/api/patrol.ts",
"frontend-modern/src/components/AI/AICostDashboard.tsx",
"frontend-modern/src/utils/aiCostPresentation.ts",
"internal/api/ai_handler.go",
"internal/api/ai_handlers.go",
"internal/api/ai_intelligence_handlers.go"
@ -884,6 +886,22 @@
"internal/api/ai_intelligence_handlers_test.go"
]
},
{
"id": "ai-cost-dashboard-surface",
"label": "AI cost dashboard proof",
"match_prefixes": [],
"match_files": [
"frontend-modern/src/components/AI/AICostDashboard.tsx",
"frontend-modern/src/utils/aiCostPresentation.ts"
],
"allow_same_subsystem_tests": false,
"test_prefixes": [],
"exact_files": [
"frontend-modern/src/components/AI/__tests__/AICostDashboard.test.tsx",
"frontend-modern/src/utils/__tests__/aiCostPresentation.test.ts",
"frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts"
]
},
{
"id": "ai-runtime-engine",
"label": "AI runtime engine proof",
@ -1984,9 +2002,12 @@
".github/workflows/deploy-demo-server.yml",
".github/workflows/release-dry-run.yml",
"Dockerfile",
"frontend-modern/package.json",
"frontend-modern/src/api/updates.ts",
"internal/api/updates.go",
"package.json",
"scripts/build-release.sh",
"scripts/dev-check.sh",
"scripts/hot-dev-bg.sh",
"scripts/hot-dev.sh",
"scripts/install-container-agent.sh",
@ -2086,6 +2107,9 @@
"label": "dev runtime orchestration proof",
"match_prefixes": [],
"match_files": [
"frontend-modern/package.json",
"package.json",
"scripts/dev-check.sh",
"scripts/hot-dev-bg.sh",
"scripts/hot-dev.sh",
"tests/integration/scripts/managed-dev-runtime.mjs"

View file

@ -14,7 +14,11 @@
},
"homepage": "https://github.com/rcourtman/Pulse",
"scripts": {
"dev": "vite",
"dev": "../scripts/hot-dev-bg.sh start --takeover",
"dev:status": "../scripts/hot-dev-bg.sh status",
"dev:stop": "../scripts/hot-dev-bg.sh stop",
"dev:verify": "../scripts/hot-dev-bg.sh verify --takeover",
"dev:frontend-only": "vite",
"build": "node scripts/build-embed-assets.mjs",
"preview": "vite preview",
"generate-types": "cd ../scripts && go run generate-types.go",

View file

@ -14,6 +14,9 @@ NC='\033[0m'
# Handle --kill flag
if [[ "${1:-}" == "--kill" ]]; then
echo "Stopping all dev processes..."
if [[ -x "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/hot-dev-bg.sh" ]]; then
"$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/hot-dev-bg.sh" stop >/dev/null 2>&1 || true
fi
pkill -9 -f "bin/pulse$" 2>/dev/null || true
pkill -9 -f "^\./pulse$" 2>/dev/null || true
pkill -f "node.*vite" 2>/dev/null || true
@ -54,13 +57,13 @@ else
echo -e "${RED}✗ NOT RESPONDING${NC}"
fi
# Check Vite frontend
echo -n "Vite frontend (port 5173): "
# Check frontend shell
echo -n "Frontend shell (port 5173): "
if curl -s -o /dev/null http://127.0.0.1:5173/ 2>/dev/null; then
echo -e "${GREEN}✓ Running${NC}"
else
echo -e "${RED}✗ NOT RUNNING${NC}"
echo " Fix: cd \${PULSE_REPOS_DIR:-\$HOME/pulse/repos}/pulse/frontend-modern && npm run dev"
echo " Fix: cd \${PULSE_REPOS_DIR:-\$HOME/pulse/repos}/pulse && npm run dev"
fi
# Check AI status

View file

@ -7,6 +7,7 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
HOT_DEV_BG="${ROOT_DIR}/scripts/hot-dev-bg.sh"
PACKAGE_JSON="${ROOT_DIR}/package.json"
FRONTEND_PACKAGE_JSON="${ROOT_DIR}/frontend-modern/package.json"
if [[ ! -x "${HOT_DEV_BG}" ]]; then
echo "hot-dev-bg.sh not found or not executable at ${HOT_DEV_BG}" >&2
@ -179,6 +180,35 @@ PY
assert_contains "root package keeps foreground escape hatch" "${output}" "dev:foreground=./scripts/hot-dev.sh"
}
test_frontend_package_exposes_managed_runtime_entrypoints() {
local output
output="$(
PACKAGE_JSON_PATH="${FRONTEND_PACKAGE_JSON}" \
python3 - <<'PY'
import json
import os
with open(os.environ["PACKAGE_JSON_PATH"], "r", encoding="utf-8") as fh:
scripts = json.load(fh)["scripts"]
for key in [
"dev",
"dev:status",
"dev:stop",
"dev:verify",
"dev:frontend-only",
]:
print(f"{key}={scripts.get(key, '')}")
PY
)"
assert_contains "frontend package exposes managed dev start" "${output}" "dev=../scripts/hot-dev-bg.sh start --takeover"
assert_contains "frontend package exposes managed dev status" "${output}" "dev:status=../scripts/hot-dev-bg.sh status"
assert_contains "frontend package exposes managed dev stop" "${output}" "dev:stop=../scripts/hot-dev-bg.sh stop"
assert_contains "frontend package exposes managed dev verify" "${output}" "dev:verify=../scripts/hot-dev-bg.sh verify --takeover"
assert_contains "frontend package keeps explicit frontend-only escape hatch" "${output}" "dev:frontend-only=vite"
}
test_backend_restart_requires_managed_runtime() {
local frontend_port backend_port output
local state_dir
@ -255,6 +285,7 @@ main() {
test_cli_parses_takeover_flag
test_verify_command_injects_managed_runtime_env
test_root_package_exposes_managed_runtime_entrypoints
test_frontend_package_exposes_managed_runtime_entrypoints
test_backend_restart_requires_managed_runtime
test_status_without_runtime
test_detects_unmanaged_listeners