| name | joint-debug |
| description | Enable, launch, monitor, troubleshoot, and stop the local joint-debug environment across conf-app, its Cloudflare Worker, ngrok, Forge tunnel, and diagramly.ai. Use for requests mentioning joint-debug, join-debug, combined local AI Repair testing, starting or monitoring the five-service stack, or closing that stack. |
Joint Debug
Run a local five-service stack:
- Diagramly AI service on
http://localhost:3000
- Cloudflare Pages Worker on
http://localhost:8789
- ngrok forwarding the configured HTTPS domain to port
8789
- conf-app frontend on
http://127.0.0.1:8080
- Forge tunnel
Guardrails
- Preserve unrelated working-tree and staged changes.
- Never print the ngrok token or database password.
- Keep
'/diagramly' in functions/_middleware.ts AUTHENTICATED_PATHS. AI routes require verified Forge JWT data in data.forgeContext.
- Keep AI Repair visibility on its existing feature-flag/runtime path. Never force
isAiRepairEnabled or shouldShowAiRepair to true.
- Use a local PostgreSQL database for Diagramly. Do not point local joint-debug at staging or production.
- Do not claim a service is ready until its log or health endpoint proves readiness.
Enable configuration
-
Inspect git status, staged and unstaged diffs, and existing JOINT-DEBUG markers.
-
Obtain the full Diagramly checkout path. Discover likely sibling checkouts first; ask only when multiple plausible paths remain.
-
Verify wrangler.toml contains NGROK_AUTHTOKEN and NGROK_DOMAIN without displaying their values.
-
In src/model/globals/forgeGlobal.ts, replace only DEVELOPMENT_LITE and DEVELOPMENT_FULL with https://<NGROK_DOMAIN> using idempotent markers:
DEVELOPMENT_LITE: 'https://<NGROK_DOMAIN>',
DEVELOPMENT_FULL: 'https://<NGROK_DOMAIN>',
-
In wrangler.toml, set DIAGRAMLY_BACKEND_API_BASE_URL = "http://localhost:3000" with TOML JOINT-DEBUG markers and preserve the original line as JOINT-DEBUG-ORIGINAL.
-
Do not modify functions/_middleware.ts or src/components/SyntaxErrorBox.vue.
-
Run git diff --check and inspect the final diff before launching services.
Prepare the Diagramly local database
First inspect packages/database/prisma/schema.prisma; Diagramly uses PostgreSQL-specific migrations and cannot be switched to SQLite as a startup-only change.
-
Reuse an existing DATABASE_URL only when its hostname is localhost or 127.0.0.1.
-
Check ports and existing containers before starting anything. Never stop an unknown PostgreSQL, Supabase, or user-owned container.
-
If no suitable local PostgreSQL exists, create a dedicated diagramly-postgres PostgreSQL 16 container. Prefer host port 5432; use 5433 or another free port when occupied.
docker run -d --name diagramly-postgres \
-e POSTGRES_USER=test_user \
-e POSTGRES_PASSWORD=test_pass \
-e POSTGRES_DB=diagramly_test \
-p 127.0.0.1:<free-port>:5432 \
postgres:16
-
Initialize the empty local database from the Diagramly root:
DATABASE_URL='<local-url>' \
pnpm --filter database exec prisma db push \
--skip-generate --schema prisma/schema.prisma
-
Keep the chosen URL as a runtime override; do not rewrite Diagramly .env unless the user explicitly asks.
-
After Diagramly starts, require GET http://127.0.0.1:3000/api/health?deep=1 to report db: "up".
The repository's .env.test.example local defaults are suitable for a dedicated test database. Treat any remote, staging, or production database URL as a configuration error for this workflow.
Launch mode
Choose based on the user's request.
Codex-managed monitoring
When the user asks Codex to start, own, monitor, or automatically diagnose the stack, do not run the AppleScript helper. Launch five long-running managed PTY sessions and retain every session ID:
DATABASE_URL='<local-url>' pnpm dev
npx wrangler pages dev --port 8789
ngrok http --authtoken '<token>' --url '<domain>' 8789
pnpm start:local
forge tunnel
If a sandboxed launch fails with EPERM, file-log permission errors, or port-binding errors, rerun that service with the required elevated permission. Do not launch pnpm start:sit: it starts another Worker and collides with the separately managed Worker.
Require these readiness signals:
- Diagramly: Next.js
Ready on port 3000, mock OpenAI server on 9000, and deep health db: "up".
- Worker:
Ready on http://localhost:8789.
- ngrok: local API on
4040 shows the configured public URL forwarding to 8789.
- Frontend: Vite
ready on 127.0.0.1:8080.
- Forge: tunnel reports its development environment and listens for requests.
User-managed Terminal windows
When the user explicitly wants separate macOS Terminal windows, run:
./.claude/skills/joint-debug/launch-debug-services.sh \
'<NGROK_AUTHTOKEN>' \
'<NGROK_DOMAIN>' \
'<DIAGRAMLY_PATH>'
The fourth argument is optional. When omitted, the helper lets Diagramly's pnpm dev load
DATABASE_URL from its default .env; the helper still verifies that it targets localhost. Pass
'<LOCAL_DATABASE_URL>' as the fourth argument only when an explicit local override is needed.
The helper requires macOS permission to send Apple Events to Terminal. If it reports error -1743, stop and tell the user to grant Automation permission or switch to Codex-managed PTYs. Never accept its success banner without checking that the expected ports are listening.
Monitor and repair
While the user tests:
- Poll all five PTY sessions after each action and retain new output.
- Correlate requests with ngrok metadata, Worker logs, Forge logs, and Diagramly logs. Avoid dumping authorization headers or request bodies containing secrets.
- Trace the user-visible error through runtime evidence before editing code.
- Apply the smallest evidence-backed fix, run focused tests, and confirm the affected service hot-reloads or restarts.
- Ask the user to retry only after the stack returns to ready state.
Known signatures:
Missing accountId in Forge context: /diagramly bypassed authentication. Restore it in AUTHENTICATED_PATHS; do not fall back to client-supplied identity.
- Diagramly returns
401 Unauthorized: inspect Diagramly logs before changing API keys. API-key auth may be masking a Prisma connection failure. Confirm deep health and the local DATABASE_URL.
- Prisma points at
diagramly-db-stg.postgres.database.azure.com: the local configuration is stale; use the dedicated local PostgreSQL database.
- Wrangler
EMFILE or listen EPERM: relaunch outside the sandbox; do not change application code.
- Forge lint errors followed by
Listening for requests: an old Forge CLI may reject newer manifest schema while the tunnel still works. Do not edit manifest.yml without separate evidence.
- Diagramly Node
>=24 warning followed by Next.js Ready: record the warning but treat it as non-blocking for that run.
Stop and clean up
- Send Ctrl+C to every managed service session and confirm exit.
- Stop
diagramly-postgres only if this workflow created or started it. Never stop unrelated Docker/Supabase containers.
- Revert only marked joint-debug changes in
src/model/globals/forgeGlobal.ts and wrangler.toml:
- remove
JOINT-DEBUG-START through JOINT-DEBUG-END blocks;
- uncomment
JOINT-DEBUG-ORIGINAL lines;
- remove marker suffixes.
- Do not change middleware authentication or AI Repair feature flags during cleanup.
- Inspect both
git diff and git diff --cached; preserve all unrelated edits.
- Confirm expected ports are no longer listening and run
git diff --check.