think
16px
820px

Plan B completion notes (2026-07-01)

State at end of Plan B

  • All 4 Docker images built + shipped to Server 2 with :latest + git-SHA tags:
  • ahu-ai-chatbot-public, ahu-ai-chatbot-internal, ahu-ai-agent-public, ahu-ai-agent-internal.
  • Three compose stacks live on Server 2 (192.168.83.20):
  • ahu-shared — Redis + pgvector (dash knowledge/learnings) + policy/config SQLite volumes + gateway-net bridge.
  • ahu-public — public-web (192.168.83.20:3500) + public-agent.
  • ahu-internal — internal-web (192.168.83.20:3510) + internal-agent.
  • All 4 app containers show Up (healthy).
  • DNS + reverse proxy:
  • x056.ahu-demo.chatbot-neo.val.id. 300 IN A 103.30.246.154 (TTL was already 300, no lowering needed).
  • Edge nginx runs on 103.30.246.154 (same box I have shell on, not a separate Hermes-controlled machine as originally assumed in the plan).
  • Site block /etc/nginx/sites-enabled/x056.ahu-demo.chatbot-neo.val.id now proxies to http://192.168.83.20:3500 (was 127.0.0.1:8120 → legacy container).
  • Pre-cutover config backed up at /etc/nginx/sites-available/x056.ahu-demo.chatbot-neo.val.id.pre-monorepo-backup.
  • Repo-committed version at infra/nginx/x056.ahu-demo.chatbot-neo.val.id.conf.
  • Legacy container retired: ahu-chatbot-dev on 127.0.0.1:8120 stopped. Old compose.dev.yaml moved to infra/legacy-compose.dev.yaml.
  • Sibling repos archived with tag archive/2026-07-01:
  • ai-ahu-data-dash (feature/orchestrator-public-data branch)
  • ahu-chatbot-orchestrator (master branch)
  • Physical dir rename (Plan A deferred): symlink ahu-ai-chatbot -> ai-ahu-chatbot still active. Physical mv deferred to a later session with no active tooling using the old path (breaking here would drop the /loop's shell context mid-stream). Non-blocking for prod.

Parity smoke results

  • Staging (Task 14): 5 orchestrate queries against 192.168.83.20:3500. All flowed through Plan→Execute→Judge→Compose, streamed Indonesian deltas via Alibaba synthesis. Snapshot: docs/superpowers/parity-snapshots/2026-07-01-staging/public-parity-smoke.txt.
  • Live prod (Task 20): 5 queries against https://x056.ahu-demo.chatbot-neo.val.id/api/orchestrate. Same end-to-end behavior. L1 guards fire correctly on Q4 (siapa direktur…) and Q5 (16-digit NIK). Snapshot: docs/superpowers/parity-snapshots/2026-07-01-staging/live-prod-smoke.txt.

Note: RAG returns empty for most questions because the staging Milvus corpus for ai-ahu-rag:8110 isn't yet loaded with AHU docs. That's a knowledge-ingestion concern, NOT an infra concern. Compose gracefully says "Berdasarkan data yang tersedia, tidak ada informasi mengenai…" which is the intended behavior when tool results are empty.

Deferrals from Plan B

  • Public DB isolation — Phase-1 caveat from spec still holds; internal.env has full-creds INTERNAL_DB_URL=mysql://bht-read@192.168.72.101/ahu_badan_hukum, public.env has no DB URL yet. Public agent operates read-only via the same connection when queried. PUBLIC_DB_URL env slot reserved for the flip when a public DB lands.
  • Model gateway serviceMODEL_GATEWAY_URL still points at direct vLLM (http://ahu-vllm:8000). Synthesis on Alibaba Cloud (transitional). When the shared gateway service lands (separate repo), flip both env vars.
  • RAG corpus ingestion — Compose smoke showed empty RAG results. Loading AHU docs into Milvus is a data-ops task, separate from Plan B's infra scope.
  • Model comparison evaldash.evals.run_model_comparison needs DASHSCOPE_API_KEY + LLM_API_KEY_LOCAL env schema separate from the runtime env. Wiring those into the eval script is Plan C hot-spot work.

Bugs found + fixed during Plan B

  1. pnpm 11.1.1 requires Node 22 — bumped Dockerfiles from node:20-alpine to node:22-alpine.
  2. empty public/ dirapps/public-web/public/ didn't exist; Docker COPY failed. Restored with .gitkeep.
  3. Agent containers idled ("chill" mode) — the agnohq entrypoint defaults to background sleep. CMD now runs uvicorn app.main:app --host 0.0.0.0 --port 8000.
  4. Shared volumes not created — compose only creates volumes services reference. deploy-staging.sh now pre-creates ahu-shared_policy-data + config-data.
  5. Postgres missing — Dash agents need pgvector. Added ahu-dash-db service to compose.shared.yaml + wired DB_* env vars.
  6. Healthcheck localhost/IPv6 — Alpine wget http://localhost:3000 tries ::1 first; Next.js only binds IPv4. Changed to 127.0.0.1.
  7. Volume ownership — Docker named volumes mount as root; container runs as uid 1001. Added entrypoint that chowns /data + /data-cfg then drops privileges via su-exec.
  8. internal-web //beranda (nonexistent) — root page now redirects to /login; healthcheck also hits /login.
  9. Alibaba synthesis URL double /v1 — LlmClient appends /v1/chat/completions; env value ended in /v1. Stripped to /compatible-mode.
  10. Port bind localhost-only — public-web bound to 127.0.0.1:3500 on Server 2 was unreachable from edge nginx. Rebound to 192.168.83.20:3500.

Commits during Plan B

383a727 chore: retire legacy ahu-chatbot-dev container + move compose.dev.yaml to infra/legacy-
194d97d cutover(2026-07-01): x056.ahu-demo.chatbot-neo.val.id  new split stack
2b5b8d3 feat(infra/nginx): x056.ahu-demo cutover site block + Hermes brief
e38de37 docs(parity): staging parity smoke 2026-07-01  5-query public orchestrate
9124afa fix(compose/internal): healthcheck hits /login
bcded09 fix(internal-web): root redirects to /login + healthcheck hits /login
a7f07d5 fix(internal-web): entrypoint chowns volumes (matched public-web fix)
285950c fix(web): entrypoint chowns /data + /data-cfg volumes to nextjs uid before starting
3992227 fix(compose): healthchecks use 127.0.0.1 (alpine wget resolves localhost via IPv6, next.js only binds IPv4)
167406e feat(infra/shared): add ahu-dash-db pgvector service + wire DB_* env vars
fd0efe9 fix(public-agent): also launch uvicorn (missed in previous commit)
57c9067 fix(agents+deploy): launch uvicorn on container start + pre-create shared volumes
b735594 feat(orchestrator): pass SYNTHESIS_API_KEY (Alibaba DashScope) through to LlmClient
cd74089 chore(gitignore): exclude infra/env/*.env (secrets) from VCS
d82f048 feat(deploy): build-and-ship, deploy-staging, rollback scripts
7c32c67 feat(infra/compose): three stacks  shared (Redis), public (web+agent), internal (web+agent)
4cbf5fe feat(agents): Dockerfiles with monorepo-root build context
253fdf2 feat(internal-web): Dockerfile with Next.js standalone build
f9d0266 feat(public-web): Dockerfile with Next.js standalone build

Success criteria check

  1. curl https://x056.ahu-demo.chatbot-neo.val.id/api/health{"ok":true,"surface":"public","timestamp":"..."}
  2. ✓ All 4 ahu-ai-* containers on Server 2 show Up (healthy)
  3. compose.dev.yaml moved to infra/legacy-compose.dev.yaml
  4. ✓ Legacy ahu-chatbot-dev container stopped
  5. ✓ Sibling repos tagged archive/2026-07-01
  6. ⊘ Physical dir rename deferred (symlink still works; non-blocking)
  7. ✓ Rollback path verified — pre-cutover nginx backup exists; rollback.sh untested but the swap is a one-line cp + nginx -t && systemctl reload.

What Plan C picks up

  • Admin scope-switcher UI (Public/Internal/Shared/Observasi nav) + audit log
  • SSE resume primitive (Last-Event-ID + Redis checkpoint)
  • Standard gateway request headers surfaced in admin
  • BullMQ workers for nightly eval + knowledge re-ingestion
  • SQL-guard TS port (Plan A hot-spot #7)
  • Dual-model streaming refactor (spec hot-spot #1)
  • Unify Dash eval script env schema with orchestrator env (so dash.evals.run_model_comparison works from staging container)
  • RAG corpus load — separate data-ops track