docs(vercel): improve Codex prompts with progress trackers, preconditions, verification gates, and per-repo checklists

This commit is contained in:
saravanakumardb1 2026-03-29 16:29:42 -07:00
parent 5fb5a7d468
commit 80e6268924
2 changed files with 619 additions and 158 deletions

View File

@ -1,16 +1,67 @@
# Track A: Azure VM — Gateway, Dashboards & Security # Track A: Azure VM — Gateway, Dashboards & Security
> **Agent:** Codex on Azure VM (`/opt/bytelyst/`) > **Agent:** Codex on Azure VM (`/opt/bytelyst/`)
> **Prompts:** 4 (run in order) > **Prompts:** 4 (run in dependency order below)
> **Dependency:** None — this track runs first, unblocks Track B Prompt 4 > **Unblocks:** Track B Prompt B4 (`.npmrc` migration — needs `gitea.bytelyst.com` live)
> **Reference docs:**
>
> - [`SECURE_API_EXPOSURE.md`](../single_azure_vm/docker/SECURE_API_EXPOSURE.md) — Caddy decision + architecture
> - [`DEPLOYMENT_STATUS_2026-03-29.md`](../single_azure_vm/docker/DEPLOYMENT_STATUS_2026-03-29.md) — current VM status
> - [`ECOSYSTEM_WEB_APPS_INVENTORY.md`](./ECOSYSTEM_WEB_APPS_INVENTORY.md) — full Vercel audit
---
## Progress Tracker
| # | Prompt | Status | Commit SHA | Verified |
| --- | ------------------------ | :------------: | :--------: | :------: |
| A1 | Caddy Gateway Setup | ⬜ Not started | — | ⬜ |
| A2 | Gitea HTTPS Exposure | ⬜ Not started | — | ⬜ |
| A3 | Dashboard Containers Fix | ⬜ Not started | — | ⬜ |
| A4 | NSG Lockdown | ⬜ Not started | — | ⬜ |
**Execution order:**
```
A1: Caddy Gateway ──→ A2: Gitea HTTPS ──→ A4: NSG Lockdown
└──→ A3: Dashboard Fix (parallel with A2)
```
---
## DNS Prerequisites (manual — do before starting)
These DNS records must exist before Caddy can obtain Let's Encrypt certificates:
| Record | Type | Value | Purpose |
| ---------------------- | ---- | ---------------------- | ------------------- |
| `api.bytelyst.com` | A | `<Azure VM public IP>` | Backend API gateway |
| `gitea.bytelyst.com` | A | `<Azure VM public IP>` | Gitea npm registry |
| `admin.bytelyst.com` | A | `<Azure VM public IP>` | Admin dashboard |
| `tracker.bytelyst.com` | A | `<Azure VM public IP>` | Tracker dashboard |
**Verify DNS before starting A1:**
```bash
dig +short api.bytelyst.com # must return VM IP
dig +short gitea.bytelyst.com # must return VM IP
```
--- ---
## A1: Caddy Gateway — Replace Traefik with Caddy ## A1: Caddy Gateway — Replace Traefik with Caddy
> **Depends on:** Nothing > **Depends on:** DNS records for `api.bytelyst.com`
> **Blocks:** A2, A3, A4 > **Blocks:** A2, A3, A4
### Preconditions
- [ ] `api.bytelyst.com` DNS A record resolves to Azure VM IP
- [ ] All 13 backend services are healthy: `docker compose ps | grep -c healthy` → 13+
- [ ] Ports 80 and 443 are open in Azure NSG
### Prompt
``` ```
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/. You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
@ -18,34 +69,66 @@ TASK: Replace the existing Traefik gateway container with Caddy to provide HTTPS
CONTEXT: CONTEXT:
- The decision doc is at docs/devops/single_azure_vm/docker/SECURE_API_EXPOSURE.md in the learning_ai_common_plat repo - The decision doc is at docs/devops/single_azure_vm/docker/SECURE_API_EXPOSURE.md in the learning_ai_common_plat repo
- The domain is bytelyst.com - The domain is bytelyst.com — DNS A records already point to this VM
- API hostname: api.bytelyst.com - API hostname: api.bytelyst.com
- Currently 13 backend services are healthy on ports 4003, 4005, 4007, 4010-4019 - Currently 13 backend services are healthy on ports 4003, 4005, 4007, 4010-4019
- Traefik is running but only as a passthrough — no TLS, no path routing hardened - Traefik is running but only as a passthrough — no TLS, no path routing hardened
- All backend containers are on a Docker network - All backend containers are on a Docker network
DELIVERABLES: TASK LIST:
1. Create a Caddyfile with: - [ ] 1. Create a Caddyfile at /opt/bytelyst/Caddyfile with:
- api.bytelyst.com as the main host (automatic Let's Encrypt TLS) - api.bytelyst.com as the main host (automatic Let's Encrypt TLS)
- Path-based routing to all 13 backends: - Path-based routing to all 13 backends:
/platform/* → platform-service:4003 /platform/* → platform-service:4003
/extraction/* → extraction-service:4005 /extraction/* → extraction-service:4005
/mcp/* → mcp-server:4007 /mcp/* → mcp-server:4007
/peakpulse/* → peakpulse:4010 /peakpulse/* → peakpulse:4010
/chronomind/* → chronomind:4011 /chronomind/* → chronomind:4011
/jarvisjr/* → jarvisjr:4012 /jarvisjr/* → jarvisjr:4012
/nomgap/* → nomgap:4013 /nomgap/* → nomgap:4013
/mindlyst/* → mindlyst:4014 /mindlyst/* → mindlyst:4014
/lysnrai/* → lysnrai:4015 /lysnrai/* → lysnrai:4015
/notelett/* → notelett:4016 /notelett/* → notelett:4016
/flowmonk/* → flowmonk:4017 /flowmonk/* → flowmonk:4017
/actiontrail/* → actiontrail:4018 /actiontrail/* → actiontrail:4018
/localmemgpt/* → localmemgpt:4019 /localmemgpt/* → localmemgpt:4019
- Strip the path prefix before forwarding (backends expect / not /platform/) - Strip the path prefix before forwarding (backends expect / not /platform/)
2. Add a caddy service to docker-compose replacing or alongside the gateway service - [ ] 2. Add a caddy service to docker-compose replacing or alongside the gateway service
3. Stop publishing backend ports (4003, 4005, 4007, 4010-4019) publicly — only expose 80/443 - Image: caddy:2-alpine
4. Verify all 13 backends respond via https://api.bytelyst.com/<service>/health - Volumes: ./Caddyfile:/etc/caddy/Caddyfile, caddy_data:/data, caddy_config:/config
5. Update docs/devops/single_azure_vm/docker/README.md with the new access model - Ports: 80:80, 443:443
- Network: same Docker network as all backends
- [ ] 3. Remove published backend ports from docker-compose (4003, 4005, 4007, 4010-4019)
— backends remain accessible internally via Docker DNS
- [ ] 4. Restart the stack: docker compose up -d
- [ ] 5. Wait for Caddy to obtain TLS certificates (check logs: docker logs caddy --tail 50)
- [ ] 6. Update docs/devops/single_azure_vm/docker/README.md with the new access model
VERIFICATION (run all — every check must pass):
# TLS certificate obtained
curl -sI https://api.bytelyst.com/platform/health | head -5
# Expected: HTTP/2 200 + valid TLS
# All 13 backends reachable via path routing
for svc in platform extraction mcp peakpulse chronomind jarvisjr nomgap mindlyst lysnrai notelett flowmonk actiontrail localmemgpt; do
echo -n "$svc: "; curl -sf https://api.bytelyst.com/$svc/health | jq -r '.status // "FAIL"'
done
# Expected: all 13 print "ok"
# Direct port access blocked from outside
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:4003/health && echo "FAIL: port still open" || echo "PASS: port closed"
# Expected: "PASS: port closed"
SUCCESS CRITERIA:
- All 13 health checks return "ok" via https://api.bytelyst.com/<service>/health
- TLS certificate is valid (Let's Encrypt)
- No backend ports (4003-4019) accessible directly from public internet
- Traefik config preserved but not in use
ROLLBACK:
If Caddy fails, revert docker-compose changes and restart Traefik:
git checkout -- docker-compose*.yml
docker compose up -d
DO NOT: DO NOT:
- Delete the existing Traefik config — just stop using it - Delete the existing Traefik config — just stop using it
@ -59,8 +142,16 @@ COMMIT: feat(gateway): replace Traefik with Caddy for HTTPS path routing
## A2: Gitea HTTPS Exposure via Caddy ## A2: Gitea HTTPS Exposure via Caddy
> **Depends on:** A1 (Caddy must be running) > **Depends on:** A1 ✅ (Caddy running + TLS working)
> **Blocks:** Track B Prompt B4 > **Blocks:** Track B → B4 (`.npmrc` update across all repos)
### Preconditions
- [ ] A1 is complete — Caddy is running with valid TLS on `api.bytelyst.com`
- [ ] `gitea.bytelyst.com` DNS A record resolves to Azure VM IP
- [ ] Gitea container is running: `docker compose ps gitea` → healthy
### Prompt
``` ```
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/. You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
@ -69,66 +160,144 @@ TASK: Expose the Gitea npm registry over HTTPS via the Caddy gateway so that ext
CONTEXT: CONTEXT:
- Gitea is running on port 3300 inside the Docker network - Gitea is running on port 3300 inside the Docker network
- Caddy is already configured for api.bytelyst.com (from A1) - Caddy is already configured for api.bytelyst.com (from A1) and has valid TLS
- The Gitea npm registry URL pattern is: /api/packages/ByteLyst/npm/ - The Gitea npm registry URL pattern is: /api/packages/ByteLyst/npm/
- Gitea needs its own subdomain because its internal routing expects to be at root - Gitea needs its own subdomain because its internal routing expects to be at root
- Target URL: https://gitea.bytelyst.com - Target URL: https://gitea.bytelyst.com
DELIVERABLES: TASK LIST:
1. Add a gitea.bytelyst.com block to the Caddyfile: - [ ] 1. Add a gitea.bytelyst.com block to the Caddyfile:
gitea.bytelyst.com { gitea.bytelyst.com {
reverse_proxy gitea:3300 reverse_proxy gitea:3300
} }
2. Ensure Gitea's ROOT_URL / SERVER__ROOT_URL is updated to https://gitea.bytelyst.com - [ ] 2. Reload Caddy: docker exec caddy caddy reload --config /etc/caddy/Caddyfile
3. Verify https://gitea.bytelyst.com loads the Gitea web UI - [ ] 3. Update Gitea's ROOT_URL to https://gitea.bytelyst.com
4. Verify npm registry is accessible: — Edit docker-compose env: SERVER__ROOT_URL=https://gitea.bytelyst.com
curl -s https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | head — Restart Gitea container: docker compose restart gitea
5. Remove port 3300 from public NSG rules (Gitea only accessible via Caddy now) - [ ] 4. Remove port 3300 from docker-compose published ports (Gitea only via Caddy)
6. Lock down other operational ports from public access where possible: - [ ] 5. Remove stale public NSG rules for ports that should not be exposed:
- 8025 (Mailpit) - 3300 (Gitea)
- 8080 (Traefik dashboard — no longer needed) - 8025 (Mailpit)
- 10000 (Azurite) - 8080 (Traefik dashboard — no longer needed)
- 10000 (Azurite)
VERIFICATION (run all — every check must pass):
# Gitea web UI loads
curl -sI https://gitea.bytelyst.com | head -3
# Expected: HTTP/2 200 (or 302 redirect to login)
# npm registry returns package metadata
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
# Expected: "@bytelyst/errors"
# Authenticated npm install works
export GITEA_NPM_TOKEN=<token>
npm view @bytelyst/errors --registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
# Expected: package info printed (version, description, etc.)
# Direct port 3300 access blocked from outside
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:3300 && echo "FAIL" || echo "PASS: port closed"
# Expected: "PASS: port closed"
# Internal Docker access still works
docker exec platform-service curl -sf http://gitea:3300/api/v1/version | jq '.version'
# Expected: Gitea version string
SUCCESS CRITERIA:
- https://gitea.bytelyst.com serves Gitea web UI with valid TLS
- npm registry API returns valid package metadata
- Authenticated `npm view` succeeds
- Port 3300 not accessible from public internet
- Docker-internal access to gitea:3300 still works (other containers unaffected)
DO NOT: DO NOT:
- Break existing Docker-internal Gitea access (other containers still use gitea:3300) - Break existing Docker-internal Gitea access (other containers still use gitea:3300)
- Remove the Gitea container or change its internal port - Remove the Gitea container or change its internal port
COMMIT: feat(gateway): expose Gitea npm registry via HTTPS at gitea.bytelyst.com COMMIT: feat(gateway): expose Gitea npm registry via HTTPS at gitea.bytelyst.com
AFTER COMPLETING: Notify the operator that Track B → B4 (.npmrc migration) is now unblocked.
``` ```
--- ---
## A3: Fix admin-web and tracker-web Containers ## A3: Fix admin-web and tracker-web Containers
> **Depends on:** A1 (Caddy gateway for subdomain routing) > **Depends on:** A1 ✅ (Caddy running for subdomain routing)
> **Blocks:** Nothing > **Blocks:** Nothing (independent of Track B)
> **Can run in parallel with:** A2
### Preconditions
- [ ] A1 is complete — Caddy is running
- [ ] `admin.bytelyst.com` and `tracker.bytelyst.com` DNS A records resolve to VM IP
- [ ] Source code for dashboards is available on the VM
### Prompt
``` ```
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/. You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
TASK: Resolve the remaining admin-web and tracker-web containers so they are running and healthy. TASK: Resolve the remaining admin-web and tracker-web containers so they are running and healthy, then expose them via Caddy.
CONTEXT: CONTEXT:
- Per DEPLOYMENT_STATUS_2026-03-29.md, all 13 backend services are healthy - Per DEPLOYMENT_STATUS_2026-03-29.md, all 13 backend services are healthy
- admin-web and tracker-web are the two remaining unresolved containers - admin-web and tracker-web are the two remaining UNRESOLVED containers
- Both are Next.js 16 apps from the learning_ai_common_plat repo under dashboards/ - Both are Next.js 16 apps from learning_ai_common_plat under dashboards/
- Both use workspace:* dependencies resolved by pnpm - Both use workspace:* dependencies resolved by pnpm
- Both use the --webpack build flag - Both use the --webpack build flag
- admin-web runs on port 3001, tracker-web on port 3003 - admin-web port: 3001, tracker-web port: 3003
- The Docker build context is dashboards/admin-web/ and dashboards/tracker-web/ - Docker build context: dashboards/admin-web/ and dashboards/tracker-web/
DELIVERABLES: TASK LIST:
1. Diagnose why admin-web and tracker-web builds failed - [ ] 1. Check current container status:
2. Fix the build issues (likely @bytelyst/* package resolution or standalone entrypoint) docker compose ps admin-web tracker-web
3. Rebuild and start both containers docker compose logs admin-web --tail 100
4. Verify health: docker compose logs tracker-web --tail 100
curl -s http://127.0.0.1:3001 | head - [ ] 2. Diagnose the build/runtime failure (likely causes):
curl -s http://127.0.0.1:3003 | head - @bytelyst/* package resolution — may need .docker-deps/ tarballs
5. Add Caddy routes for the dashboards: - Standalone entrypoint not found
- https://admin.bytelyst.com → admin-web:3001 - Missing env vars (COSMOS_ENDPOINT, COSMOS_KEY, JWT_SECRET)
- https://tracker.bytelyst.com → tracker-web:3003 - [ ] 3. Fix the identified issues
6. Update DEPLOYMENT_STATUS_2026-03-29.md to reflect the fix - [ ] 4. Rebuild and restart:
7. Mark Phase 7 as DONE if all services are now healthy docker compose up -d --build admin-web tracker-web
- [ ] 5. Add Caddy routes for the dashboards to the Caddyfile:
admin.bytelyst.com {
reverse_proxy admin-web:3001
}
tracker.bytelyst.com {
reverse_proxy tracker-web:3003
}
- [ ] 6. Reload Caddy: docker exec caddy caddy reload --config /etc/caddy/Caddyfile
- [ ] 7. Update DEPLOYMENT_STATUS_2026-03-29.md to reflect the fix
VERIFICATION (run all — every check must pass):
# Containers healthy
docker compose ps admin-web tracker-web
# Expected: both show "Up" and "healthy" (or at least "Up")
# Local port access
curl -sf http://127.0.0.1:3001 | head -5
curl -sf http://127.0.0.1:3003 | head -5
# Expected: HTML response from each
# HTTPS via Caddy
curl -sI https://admin.bytelyst.com | head -3
# Expected: HTTP/2 200 (or 302)
curl -sI https://tracker.bytelyst.com | head -3
# Expected: HTTP/2 200 (or 302)
# All containers now healthy
docker compose ps | grep -E "(unhealthy|Exit)" | wc -l
# Expected: 0
SUCCESS CRITERIA:
- Both admin-web and tracker-web containers are running
- Both respond on their ports (3001, 3003)
- Both accessible via HTTPS at admin.bytelyst.com and tracker.bytelyst.com
- DEPLOYMENT_STATUS doc updated with fix details
- Zero unhealthy containers in the full stack
COMMIT: fix(deployment): resolve admin-web and tracker-web containers COMMIT: fix(deployment): resolve admin-web and tracker-web containers
``` ```
@ -137,41 +306,126 @@ COMMIT: fix(deployment): resolve admin-web and tracker-web containers
## A4: NSG Lockdown — Reduce Public Port Exposure ## A4: NSG Lockdown — Reduce Public Port Exposure
> **Depends on:** A1 + A2 (Caddy handling all traffic) > **Depends on:** A1 + A2 + A3 all complete (all traffic routed through Caddy)
> **Blocks:** Nothing > **Blocks:** Nothing
> **Run this LAST in Track A**
### Preconditions
- [ ] A1 complete — all backends accessible via `api.bytelyst.com`
- [ ] A2 complete — Gitea accessible via `gitea.bytelyst.com`
- [ ] A3 complete — dashboards accessible via `admin.bytelyst.com` and `tracker.bytelyst.com`
- [ ] All services verified working through Caddy (no direct port access needed)
### Prompt
``` ```
TASK: Reduce the Azure NSG (Network Security Group) rules so only ports 80, 443, and 22 are publicly accessible. TASK: Reduce the Azure NSG (Network Security Group) rules so only ports 80, 443, and 22 are publicly accessible.
CONTEXT: CONTEXT:
- The Azure VM currently exposes many service ports publicly (3000-3300, 4003-4019, 8025, 8080, 10000, 11434) - The Azure VM currently exposes many service ports publicly (3000-3300, 4003-4019, 8025, 8080, 10000, 11434)
- Caddy now handles all public HTTPS traffic on 80/443 - Caddy now handles ALL public HTTPS traffic on ports 80/443
- Backend services, Gitea, Grafana, Mailpit, and Azurite are all accessed through Caddy - All services (backends, Gitea, dashboards, monitoring) are accessed through Caddy subdomains
- Only SSH (22) and HTTP/HTTPS (80/443) should remain publicly open - Only SSH (22) and HTTP/HTTPS (80/443) should remain publicly open
- This follows the recommendation in SECURE_API_EXPOSURE.md - This follows the recommendation in SECURE_API_EXPOSURE.md
DELIVERABLES: TASK LIST:
1. List current NSG rules: az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table - [ ] 1. Snapshot current NSG rules (save output for rollback reference):
2. Remove or deny inbound rules for all ports except 22, 80, 443 az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table > /opt/bytelyst/nsg-rules-before.txt
3. Verify Caddy still serves all routes correctly cat /opt/bytelyst/nsg-rules-before.txt
4. Verify SSH access still works - [ ] 2. Identify rules to remove — everything except:
5. Document the changes in DEPLOYMENT_STATUS_2026-03-29.md - SSH (22/tcp)
- HTTP (80/tcp)
- HTTPS (443/tcp)
- [ ] 3. Delete each unnecessary rule:
az network nsg rule delete --resource-group <rg> --nsg-name <nsg> --name <rule-name>
- [ ] 4. List final NSG rules to confirm only 3 remain:
az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table
- [ ] 5. Document changes in DEPLOYMENT_STATUS_2026-03-29.md
VERIFICATION (run all — every check must pass):
# SSH still works
ssh -o ConnectTimeout=5 <user>@<VM_IP> echo "SSH OK"
# Expected: "SSH OK"
# Caddy still serves all routes
curl -sf https://api.bytelyst.com/platform/health | jq '.status'
# Expected: "ok"
curl -sf https://gitea.bytelyst.com/api/v1/version | jq '.version'
# Expected: version string
curl -sI https://admin.bytelyst.com | head -1
# Expected: HTTP/2 200 (or 302)
# Direct port access blocked
for port in 3001 3003 3300 4003 4005 8025 8080 10000; do
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:$port && echo "FAIL: $port open" || echo "PASS: $port closed"
done
# Expected: all "PASS: <port> closed"
# Only 3 NSG rules remain
az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table | grep -c Allow
# Expected: 3 (SSH, HTTP, HTTPS)
SUCCESS CRITERIA:
- Only ports 22, 80, 443 open in NSG
- SSH access confirmed working
- All Caddy routes still functional
- No direct port access possible from public internet
- Before/after NSG snapshots saved
ROLLBACK:
If services become unreachable after lockdown:
# Re-add a rule temporarily
az network nsg rule create --resource-group <rg> --nsg-name <nsg> \
--name AllowTemp --priority 200 --access Allow --direction Inbound \
--source-address-prefixes '*' --destination-port-ranges <port> --protocol Tcp
# Then investigate Caddy routing
DO NOT: DO NOT:
- Remove the SSH (22) rule - Remove the SSH (22) rule — you will lose access
- Remove the HTTP (80) or HTTPS (443) rules - Remove the HTTP (80) or HTTPS (443) rules — Caddy needs them
- Make changes without first listing the current rules - Make changes without first saving the current rules snapshot
COMMIT: chore(security): lock down Azure NSG to 22/80/443 only COMMIT: chore(security): lock down Azure NSG to 22/80/443 only
``` ```
--- ---
## Track A Execution Order ## Track A — Final Verification Checklist
``` After all 4 prompts are complete, run this full end-to-end verification:
A1: Caddy Gateway ──→ A2: Gitea HTTPS ──→ A4: NSG Lockdown
└──→ A3: Dashboards Fix ```bash
echo "=== Track A Final Verification ==="
echo "--- DNS ---"
for d in api.bytelyst.com gitea.bytelyst.com admin.bytelyst.com tracker.bytelyst.com; do
echo -n "$d → "; dig +short $d
done
echo "--- Backend Health (13 services) ---"
for svc in platform extraction mcp peakpulse chronomind jarvisjr nomgap mindlyst lysnrai notelett flowmonk actiontrail localmemgpt; do
echo -n "$svc: "; curl -sf https://api.bytelyst.com/$svc/health | jq -r '.status // "FAIL"'
done
echo "--- Gitea npm registry ---"
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
echo "--- Dashboards ---"
curl -sI https://admin.bytelyst.com | head -1
curl -sI https://tracker.bytelyst.com | head -1
echo "--- Port lockdown ---"
for port in 3001 3003 3300 4003 4005 8025 8080 10000; do
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:$port > /dev/null 2>&1 && echo "FAIL: $port open" || echo "PASS: $port closed"
done
echo "--- Docker containers ---"
docker compose ps --format 'table {{.Name}}\t{{.Status}}' | grep -E "(unhealthy|Exit)" | wc -l
# Expected: 0
``` ```
A3 can run in parallel with A2. A4 runs last after everything is routed through Caddy. **All checks must pass before Track A is considered complete.**
Once A2 verification passes, signal to Track B that Prompt B4 is unblocked.

View File

@ -2,6 +2,29 @@
> **Agent:** Any Codex agent with repo access (local or cloud) > **Agent:** Any Codex agent with repo access (local or cloud)
> **Prompts:** 4 (B1B3 run in parallel, B4 runs last after Track A completes A2) > **Prompts:** 4 (B1B3 run in parallel, B4 runs last after Track A completes A2)
> **Reference docs:**
>
> - [`ECOSYSTEM_WEB_APPS_INVENTORY.md`](./ECOSYSTEM_WEB_APPS_INVENTORY.md) — full Vercel audit + per-app status
> - Individual `ROADMAP_*.md` files — per-app gaps, env vars, and deployment steps
---
## Progress Tracker
| # | Prompt | Repos | Status | Commits | Verified |
| --- | ------------------------ | :---: | :--------------: | :-----: | :------: |
| B1 | Fix `file:` refs | 7 | ⬜ Not started | 0/7 | ⬜ |
| B2 | Fix `output: standalone` | 4 | ⬜ Not started | 0/4 | ⬜ |
| B3 | EffoRise `vercel.json` | 1 | ⬜ Not started | 0/1 | ⬜ |
| B4 | Update `.npmrc` | 12 | ⬜ Blocked on A2 | 0/12 | ⬜ |
**Execution order:**
```
B1: Fix file: refs ──────┐
B2: Fix standalone ──────┼──→ B4: Update .npmrc (blocked until Track A → A2 done)
B3: EffoRise vercel.json ┘
```
--- ---
@ -10,15 +33,28 @@
> **Depends on:** Nothing (packages are already published to Gitea) > **Depends on:** Nothing (packages are already published to Gitea)
> **Blocks:** Nothing > **Blocks:** Nothing
### Per-Repo Checklist
| # | Repo | File | Packages to fix | Edited | Built | Committed | Pushed |
| --- | ------------------------------ | ------------------------ | ----------------- | :----: | :---: | :-------: | :----: |
| 1 | `learning_ai_clock` | `web/package.json` | design-tokens, ui | ⬜ | ⬜ | ⬜ | ⬜ |
| 2 | `learning_ai_jarvis_jr` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
| 3 | `learning_ai_fastgap` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
| 4 | `learning_ai_flowmonk` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
| 5 | `learning_ai_notes` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
| 6 | `learning_ai_local_memory_gpt` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
| 7 | `learning_ai_local_llms` | `dashboard/package.json` | design-tokens, ui | ⬜ | ⬜ | ⬜ | ⬜ |
### Prompt
``` ```
TASK: Convert all file: references to @bytelyst/* packages into semver ^0.1.0 references across 7 web app repos. TASK: Convert all file: references to @bytelyst/* packages into semver ^0.1.0 references across 7 web app repos.
CONTEXT: CONTEXT:
- 7 repos have web/package.json files that use file: references to ../../learning_ai_common_plat/packages/* - 7 repos have web/package.json (or dashboard/package.json) files with file: references to ../../learning_ai_common_plat/packages/*
- These fail on Vercel because the sibling repo doesn't exist - These fail on Vercel because the sibling repo doesn't exist during build
- The packages are already published to the Gitea npm registry - The packages are already published to the Gitea npm registry
- Each fix is: change "file:../../learning_ai_common_plat/packages/X" to "^0.1.0" - Each fix: change "file:../../learning_ai_common_plat/packages/X" to "^0.1.0"
- After changing, run pnpm install to update the lockfile, then verify pnpm build passes
REPOS AND FILES TO FIX: REPOS AND FILES TO FIX:
@ -45,17 +81,35 @@ REPOS AND FILES TO FIX:
- "@bytelyst/design-tokens": "file:..." → "^0.1.0" - "@bytelyst/design-tokens": "file:..." → "^0.1.0"
- "@bytelyst/ui": "file:..." → "^0.1.0" - "@bytelyst/ui": "file:..." → "^0.1.0"
FOR EACH REPO: FOR EACH REPO (repeat 7 times):
1. Edit the package.json — replace file: refs with ^0.1.0 - [ ] 1. Edit the package.json — replace file: refs with ^0.1.0
2. Run: cd web && pnpm install (or cd dashboard for LLM Lab) - [ ] 2. Run: cd web && pnpm install (or cd dashboard for LLM Lab)
3. Run: pnpm build - [ ] 3. Verify no file: refs remain: grep -r "file:.*common_plat" package.json
4. If build passes, commit: fix(web): convert file: refs to registry semver for Vercel compatibility Expected: no output
5. Push to origin main - [ ] 4. Run: pnpm build
Expected: build succeeds with exit code 0
- [ ] 5. Commit: fix(web): convert file: refs to registry semver for Vercel compatibility
- [ ] 6. Push to origin main
VERIFICATION (after all 7 repos):
# Confirm zero file: refs remain across all repos
for repo in learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_local_memory_gpt learning_ai_local_llms; do
echo -n "$repo: "
grep -rl "file:.*common_plat" $repo/web/package.json $repo/dashboard/package.json 2>/dev/null | wc -l | tr -d ' '
echo " file: refs remaining"
done
# Expected: all show "0 file: refs remaining"
SUCCESS CRITERIA:
- All 7 repos have zero file: references in their web/dashboard package.json
- All 7 builds pass (pnpm build exits 0)
- All 7 commits pushed to origin main
- No other dependencies or source code modified
DO NOT: DO NOT:
- Change any other dependencies - Change any other dependencies
- Modify any source code - Modify any source code
- Skip the build verification step - Skip the build verification step for any repo
``` ```
--- ---
@ -65,16 +119,28 @@ DO NOT:
> **Depends on:** Nothing > **Depends on:** Nothing
> **Blocks:** Nothing > **Blocks:** Nothing
### Per-Repo Checklist
| # | Repo | File | Pattern | Edited | Docker Build | Vercel Build | Committed | Pushed |
| --- | ------------------------------ | -------------------- | --------------------- | :----: | :----------: | :----------: | :-------: | :----: |
| 1 | `learning_ai_fastgap` | `web/next.config.ts` | output + tracing root | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
| 2 | `learning_ai_notes` | `web/next.config.ts` | output + tracing root | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
| 3 | `learning_ai_trails` | `web/next.config.ts` | output only | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
| 4 | `learning_ai_local_memory_gpt` | `web/next.config.ts` | output only | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
> **Skip:** `learning_ai_local_llms/dashboard/next.config.ts` — LLM Lab not viable on Vercel (needs local Ollama)
### Prompt
``` ```
TASK: Make the Next.js output mode Vercel-aware in 4 repos that currently hardcode output: 'standalone'. TASK: Make the Next.js output mode Vercel-aware in 4 repos that currently hardcode output: 'standalone'.
CONTEXT: CONTEXT:
- Vercel manages its own output mode — hardcoded standalone breaks Vercel builds - Vercel manages its own output mode — hardcoded standalone breaks Vercel builds
- The fix is: wrap standalone output in a process.env.VERCEL conditional - The fix: wrap standalone output in a process.env.VERCEL conditional
- Docker builds (which don't set VERCEL env var) will still get standalone mode - Docker builds (which don't set VERCEL env var) will still get standalone mode
- 4 repos need this fix
REPOS AND FILES: REPOS AND EXACT CHANGES:
1. learning_ai_fastgap/web/next.config.ts 1. learning_ai_fastgap/web/next.config.ts
Change: Change:
@ -87,7 +153,7 @@ REPOS AND FILES:
}), }),
2. learning_ai_notes/web/next.config.ts 2. learning_ai_notes/web/next.config.ts
Same pattern as above. Same pattern as #1 (output + outputFileTracingRoot).
3. learning_ai_trails/web/next.config.ts 3. learning_ai_trails/web/next.config.ts
Change: Change:
@ -96,16 +162,36 @@ REPOS AND FILES:
...(process.env.VERCEL ? {} : { output: 'standalone' }), ...(process.env.VERCEL ? {} : { output: 'standalone' }),
4. learning_ai_local_memory_gpt/web/next.config.ts 4. learning_ai_local_memory_gpt/web/next.config.ts
Same pattern as #3. Same pattern as #3 (output only).
NOTE: learning_ai_local_llms/dashboard/next.config.ts also has this but LLM Lab is NOT viable on Vercel (needs local Ollama), so skip it. FOR EACH REPO (repeat 4 times):
- [ ] 1. Edit next.config.ts with the VERCEL conditional
- [ ] 2. Verify Docker build still works (standalone activates without VERCEL env):
cd web && pnpm build
# Check output: look for "Creating an optimized production build" + ".next/standalone/" dir
ls -d .next/standalone/ && echo "PASS: standalone created" || echo "FAIL"
- [ ] 3. Verify Vercel-mode build works (standalone skipped with VERCEL env):
cd web && VERCEL=1 pnpm build
# Check output: .next/standalone/ should NOT exist
ls -d .next/standalone/ 2>/dev/null && echo "FAIL: standalone still created" || echo "PASS: no standalone"
- [ ] 4. Commit: fix(web): make output mode Vercel-aware — conditional standalone
- [ ] 5. Push to origin main
FOR EACH REPO: VERIFICATION (after all 4 repos):
1. Edit next.config.ts with the conditional for repo in learning_ai_fastgap learning_ai_notes learning_ai_trails learning_ai_local_memory_gpt; do
2. Verify Docker build still works: pnpm build (standalone should still activate without VERCEL env) echo "=== $repo ==="
3. Verify VERCEL=1 pnpm build also works (output should be default, not standalone) cd $repo/web
4. Commit: fix(web): make output mode Vercel-aware — conditional standalone grep -c "process.env.VERCEL" next.config.ts
5. Push to origin main # Expected: 1 (the conditional)
cd ../..
done
SUCCESS CRITERIA:
- All 4 next.config.ts files contain process.env.VERCEL conditional
- Docker build (no VERCEL env) produces .next/standalone/
- Vercel build (VERCEL=1) does NOT produce .next/standalone/
- All 4 commits pushed to origin main
- No other config options changed
DO NOT: DO NOT:
- Change any other config options in next.config.ts - Change any other config options in next.config.ts
@ -120,33 +206,63 @@ DO NOT:
> **Depends on:** Nothing > **Depends on:** Nothing
> **Blocks:** Nothing > **Blocks:** Nothing
### Checklist
| Step | Description | Done |
| ---- | ------------------------- | :--: |
| 1 | Create `vercel.json` | ⬜ |
| 2 | Verify local build | ⬜ |
| 3 | Verify SPA routing config | ⬜ |
| 4 | Commit + push | ⬜ |
### Prompt
``` ```
TASK: Create a vercel.json file for the EffoRise Vite SPA to handle client-side routing and API proxy configuration. TASK: Create a vercel.json file for the EffoRise Vite SPA to handle client-side routing and API proxy configuration.
CONTEXT: CONTEXT:
- EffoRise is a Vite + React 19 SPA (not Next.js) in the learning_ai_efforise repo - EffoRise is a Vite + React 19 SPA (NOT Next.js) in the learning_ai_efforise repo
- The Vite config is at the repo root (vite.config.ts) - The Vite config is at the repo root (client/ directory has the SPA)
- Build output goes to dist/public/ (custom, not default dist/) - Build output goes to dist/public/ (custom, not default dist/)
- Uses wouter for client-side routing — all routes must serve index.html - Uses wouter for client-side routing — all routes must serve index.html
- The backend API is at https://api.bytelyst.com/efforise - The backend API is at https://api.bytelyst.com/efforise
- Currently uses a dev proxy /api → localhost:4020 - Currently uses a dev proxy /api → localhost:4020
DELIVERABLES: TASK LIST:
1. Create vercel.json at the repo root with: - [ ] 1. Create client/vercel.json with:
{ {
"$schema": "https://openapi.vercel.sh/vercel.json", "$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "vite", "framework": "vite",
"buildCommand": "pnpm build", "buildCommand": "pnpm build",
"outputDirectory": "dist/public", "outputDirectory": "dist/public",
"rewrites": [ "rewrites": [
{ "source": "/api/(.*)", "destination": "https://api.bytelyst.com/efforise/$1" }, { "source": "/api/(.*)", "destination": "https://api.bytelyst.com/efforise/$1" },
{ "source": "/(.*)", "destination": "/index.html" } { "source": "/(.*)", "destination": "/index.html" }
] ]
} }
- [ ] 2. Verify local build: cd client && pnpm build
Expected: exit code 0, dist/public/index.html exists
- [ ] 3. Verify vercel.json is valid JSON: cat client/vercel.json | jq .
Expected: formatted JSON output, no parse errors
- [ ] 4. Commit: feat(web): add vercel.json for Vite SPA deployment
- [ ] 5. Push to origin main
2. Verify pnpm build still works locally VERIFICATION:
3. Commit: feat(web): add vercel.json for Vite SPA deployment # Build works
4. Push to origin main cd client && pnpm build && echo "BUILD: PASS" || echo "BUILD: FAIL"
# Output directory exists
ls client/dist/public/index.html && echo "OUTPUT: PASS" || echo "OUTPUT: FAIL"
# vercel.json valid
jq '.rewrites | length' client/vercel.json
# Expected: 2
SUCCESS CRITERIA:
- client/vercel.json exists with correct framework, build command, output directory, and rewrites
- Local build still produces dist/public/index.html
- vercel.json is valid JSON
- Commit pushed to origin main
DO NOT: DO NOT:
- Modify vite.config.ts - Modify vite.config.ts
@ -158,12 +274,44 @@ DO NOT:
## B4: Update .npmrc Across All Product Repos ## B4: Update .npmrc Across All Product Repos
> **Depends on:** Track A Prompt A2 (gitea.bytelyst.com must be live and accessible) > **Depends on:** Track A → A2 complete (`gitea.bytelyst.com` live + verified)
> **Blocks:** Vercel deployment > **Blocks:** All Vercel deployments (this is the final gate)
### Pre-flight Check (must pass before starting)
```bash
# Verify gitea.bytelyst.com is live and serving packages
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
# Expected: "@bytelyst/errors"
# If this fails, DO NOT proceed — Track A → A2 is not complete
```
### Per-Repo Checklist
| # | Repo | .npmrc locations | Updated | Install OK | Committed | Pushed |
| --- | ----------------------------------- | -------------------------- | :-----: | :--------: | :-------: | :----: |
| 1 | `learning_voice_ai_agent` | root, user-dashboard-web/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 2 | `learning_ai_clock` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 3 | `learning_ai_jarvis_jr` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 4 | `learning_ai_fastgap` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 5 | `learning_ai_flowmonk` | root, web/, mobile/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 6 | `learning_ai_notes` | root, web/, mobile/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 7 | `learning_ai_trails` | root, web/, sdk/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 8 | `learning_multimodal_memory_agents` | root, mindlyst-native/web/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 9 | `learning_ai_local_memory_gpt` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 10 | `learning_ai_efforise` | root, mobile/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 11 | `learning_ai_local_llms` | dashboard/ | ⬜ | ⬜ | ⬜ | ⬜ |
| 12 | `learning_ai_peakpulse` | root | ⬜ | ⬜ | ⬜ | ⬜ |
### Prompt
``` ```
TASK: Update .npmrc files in all product repos to point to the public Gitea npm registry at gitea.bytelyst.com. TASK: Update .npmrc files in all product repos to point to the public Gitea npm registry at gitea.bytelyst.com.
PRE-FLIGHT (must pass before starting):
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
# Must return "@bytelyst/errors" — if not, STOP and report that Track A → A2 is not done
CONTEXT: CONTEXT:
- All product repos currently have .npmrc pointing to http://localhost:3300 (local Gitea) - All product repos currently have .npmrc pointing to http://localhost:3300 (local Gitea)
- Gitea is now accessible at https://gitea.bytelyst.com via Caddy reverse proxy - Gitea is now accessible at https://gitea.bytelyst.com via Caddy reverse proxy
@ -171,67 +319,126 @@ CONTEXT:
- Auth token is passed via GITEA_NPM_TOKEN env var - Auth token is passed via GITEA_NPM_TOKEN env var
- This change enables Vercel builds to install @bytelyst/* packages - This change enables Vercel builds to install @bytelyst/* packages
NEW .npmrc CONTENT (same for all repos): TARGET .npmrc CONTENT (same for all repos):
@bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/ @bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
//gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN} //gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN}
REPOS TO UPDATE (12 total): REPOS TO UPDATE (12 total — see checklist above for .npmrc locations):
1. learning_voice_ai_agent (user-dashboard-web, backend) 1. learning_voice_ai_agent (root .npmrc + user-dashboard-web/.npmrc)
2. learning_ai_clock (web, backend) 2. learning_ai_clock (root + web/)
3. learning_ai_jarvis_jr (web, backend) 3. learning_ai_jarvis_jr (root + web/)
4. learning_ai_fastgap (web, backend) 4. learning_ai_fastgap (root + web/)
5. learning_ai_flowmonk (web, backend, mobile) 5. learning_ai_flowmonk (root + web/ + mobile/)
6. learning_ai_notes (web, backend, mobile) 6. learning_ai_notes (root + web/ + mobile/)
7. learning_ai_trails (web, backend, sdk) 7. learning_ai_trails (root + web/ + sdk/)
8. learning_multimodal_memory_agents (mindlyst-native/web, backend) 8. learning_multimodal_memory_agents (root + mindlyst-native/web/)
9. learning_ai_local_memory_gpt (web, backend) 9. learning_ai_local_memory_gpt (root + web/)
10. learning_ai_efforise (root, backend, mobile) 10. learning_ai_efforise (root + mobile/)
11. learning_ai_local_llms (dashboard) 11. learning_ai_local_llms (dashboard/)
12. learning_ai_peakpulse (backend) 12. learning_ai_peakpulse (root)
FOR EACH REPO: FOR EACH REPO (repeat 12 times):
1. Find all .npmrc files (there may be multiple — root, web/, backend/, mobile/) - [ ] 1. Find all .npmrc files: find . -name ".npmrc" -not -path "*/node_modules/*"
2. Update the @bytelyst registry line to use gitea.bytelyst.com - [ ] 2. In each .npmrc, replace the @bytelyst registry line:
3. Add the auth token line if not present OLD: @bytelyst:registry=http://localhost:3300/api/packages/ByteLyst/npm/
4. Run: GITEA_NPM_TOKEN=<token> pnpm install (verify packages resolve) NEW: @bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
5. Commit: chore: update .npmrc to public Gitea registry at gitea.bytelyst.com - [ ] 3. Ensure the auth token line exists:
6. Push to origin main //gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN}
- [ ] 4. Verify no localhost:3300 references remain:
grep -r "localhost:3300" . --include=".npmrc"
Expected: no output
- [ ] 5. Verify packages resolve:
GITEA_NPM_TOKEN=<token> pnpm install
Expected: exit code 0, all @bytelyst/* packages resolved
- [ ] 6. Commit: chore: update .npmrc to public Gitea registry at gitea.bytelyst.com
- [ ] 7. Push to origin main
VERIFICATION: VERIFICATION (after all 12 repos — run from parent directory containing all repos):
After updating all repos, verify one end-to-end: echo "=== .npmrc Migration Verification ==="
# Check no localhost:3300 remains anywhere
for repo in learning_voice_ai_agent learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_trails learning_multimodal_memory_agents learning_ai_local_memory_gpt learning_ai_efforise learning_ai_local_llms learning_ai_peakpulse; do
count=$(grep -rl "localhost:3300" $repo/ --include=".npmrc" 2>/dev/null | wc -l | tr -d ' ')
echo "$repo: $count old refs remaining"
done
# Expected: all show "0 old refs remaining"
# End-to-end build test on one repo
cd learning_ai_clock/web cd learning_ai_clock/web
GITEA_NPM_TOKEN=<token> pnpm install GITEA_NPM_TOKEN=<token> pnpm install && pnpm build && echo "E2E: PASS" || echo "E2E: FAIL"
pnpm build # Expected: "E2E: PASS"
SUCCESS CRITERIA:
- All 12 repos have zero localhost:3300 references in .npmrc files
- All 12 repos can resolve @bytelyst/* packages via gitea.bytelyst.com
- At least one repo verified with full pnpm install + pnpm build
- All 12 commits pushed to origin main
- No package versions changed, no auth tokens hardcoded
DO NOT: DO NOT:
- Change any package versions - Change any package versions
- Remove any other registry configurations (e.g., npmjs.org for non-@bytelyst packages) - Remove any other registry configurations (e.g., npmjs.org for non-@bytelyst packages)
- Hardcode the auth token — always use ${GITEA_NPM_TOKEN} - Hardcode the auth token — always use ${GITEA_NPM_TOKEN}
- Proceed if the pre-flight check fails
``` ```
--- ---
## Track B Execution Order ## Track B — Final Verification Checklist
``` After all 4 prompts are complete, verify the full picture:
B1: Fix file: refs ──────┐
B2: Fix standalone ──────┼──→ B4: Update .npmrc (waits for Track A → A2) ```bash
B3: EffoRise vercel.json ┘ echo "=== Track B Final Verification ==="
echo "--- B1: file: refs (7 repos) ---"
for repo in learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_local_memory_gpt learning_ai_local_llms; do
count=$(grep -rl "file:.*common_plat" $repo/web/package.json $repo/dashboard/package.json 2>/dev/null | wc -l | tr -d ' ')
echo "$repo: $count file: refs"
done
# Expected: all 0
echo "--- B2: standalone conditional (4 repos) ---"
for repo in learning_ai_fastgap learning_ai_notes learning_ai_trails learning_ai_local_memory_gpt; do
count=$(grep -c "process.env.VERCEL" $repo/web/next.config.ts 2>/dev/null)
echo "$repo: $count VERCEL conditionals"
done
# Expected: all 1
echo "--- B3: EffoRise vercel.json ---"
jq '.rewrites | length' learning_ai_efforise/client/vercel.json 2>/dev/null
# Expected: 2
echo "--- B4: .npmrc migration (12 repos) ---"
for repo in learning_voice_ai_agent learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_trails learning_multimodal_memory_agents learning_ai_local_memory_gpt learning_ai_efforise learning_ai_local_llms learning_ai_peakpulse; do
count=$(grep -rl "localhost:3300" $repo/ --include=".npmrc" 2>/dev/null | wc -l | tr -d ' ')
echo "$repo: $count old .npmrc refs"
done
# Expected: all 0
``` ```
B1, B2, B3 can all run in parallel immediately. B4 must wait until `gitea.bytelyst.com` is live (Track A, Prompt A2). **All checks must pass before Track B is considered complete.**
--- ---
## After Both Tracks Complete ## After Both Tracks Complete — Vercel Project Setup (Manual)
``` Once Track A and Track B are both verified, the remaining work is manual in the Vercel UI:
Manual steps (Vercel UI):
→ Create Vercel projects for each app
→ Set GITEA_NPM_TOKEN + other env vars per project
→ Trigger first deploys and verify
```
See [`ECOSYSTEM_WEB_APPS_INVENTORY.md`](./ECOSYSTEM_WEB_APPS_INVENTORY.md) for the full app list and per-app environment variables. | # | App | Vercel Root Dir | Framework | Key Env Vars | Roadmap |
See individual `ROADMAP_*.md` files for per-app Vercel project setup details. | --- | ----------------- | ------------------------ | --------- | ------------------------------------------------------ | ---------------------------------------------------------- |
| 1 | Admin Dashboard | `dashboards/admin-web` | Next.js | `COSMOS_ENDPOINT`, `COSMOS_KEY`, `JWT_SECRET` | [ROADMAP_ADMIN_WEB.md](./ROADMAP_ADMIN_WEB.md) |
| 2 | Tracker Dashboard | `dashboards/tracker-web` | Next.js | `JWT_SECRET`, `PLATFORM_SERVICE_URL` | [ROADMAP_TRACKER_WEB.md](./ROADMAP_TRACKER_WEB.md) |
| 3 | User Dashboard | `user-dashboard-web` | Next.js | `PLATFORM_SERVICE_URL`, `ACTIONTRAIL_SERVICE_URL` | [ROADMAP_USER_DASHBOARD.md](./ROADMAP_USER_DASHBOARD.md) |
| 4 | ChronoMind Web | `web` | Next.js | `GITEA_NPM_TOKEN` | [ROADMAP_CHRONOMIND_WEB.md](./ROADMAP_CHRONOMIND_WEB.md) |
| 5 | JarvisJr Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_PLATFORM_URL` | [ROADMAP_JARVISJR_WEB.md](./ROADMAP_JARVISJR_WEB.md) |
| 6 | NomGap Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_NOMGAP_WEB.md](./ROADMAP_NOMGAP_WEB.md) |
| 7 | FlowMonk Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_FLOWMONK_WEB.md](./ROADMAP_FLOWMONK_WEB.md) |
| 8 | NoteLett Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_NOTELETT_WEB.md](./ROADMAP_NOTELETT_WEB.md) |
| 9 | ActionTrail Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_ACTIONTRAIL_WEB.md](./ROADMAP_ACTIONTRAIL_WEB.md) |
| 10 | MindLyst Web | `mindlyst-native/web` | Next.js | `GITEA_NPM_TOKEN`, `COSMOS_ENDPOINT`, `OPENAI_API_KEY` | [ROADMAP_MINDLYST_WEB.md](./ROADMAP_MINDLYST_WEB.md) |
| 11 | LocalMemGPT Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_LOCALMEMGPT_WEB.md](./ROADMAP_LOCALMEMGPT_WEB.md) |
| 12 | EffoRise Client | `client` | Vite | `GITEA_NPM_TOKEN`, `VITE_BACKEND_URL` | [ROADMAP_EFFORISE.md](./ROADMAP_EFFORISE.md) |
**Every Vercel project needs `GITEA_NPM_TOKEN` set.** See individual roadmap files for the complete env var list per app.