From e9dfb9b59ca435f8e67053fec85e7170cdb9615f Mon Sep 17 00:00:00 2001 From: ichandrasharma Date: Mon, 7 Sep 2026 17:21:18 +0530 Subject: [PATCH 1/6] docs(agent-coordination): document backend login issue and resolution steps --- AGENT_COORDINATION.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/AGENT_COORDINATION.md b/AGENT_COORDINATION.md index 9e7d96e7d..5475eabf1 100644 --- a/AGENT_COORDINATION.md +++ b/AGENT_COORDINATION.md @@ -260,3 +260,23 @@ no-inheritance, owner-filter), `tests/core/test_knowledge_spotlighting.py` 10/10 threading), assembler/agents/status/memory-index 126/126. py_compile clean. fetch-state file pollution made the new-owner test order-sensitive — the test now clears its own per-owner key first (test residue under `backend/data/` is gitignored). + +--- + +## 2026-09-03 - Codex session: localhost login unavailable + +**Context**: User reported `/login?callbackUrl=http://localhost:3000/dashboard` +showing "Invalid email or password" for `admin@example.com` / `securePass123`, +with logs showing `ECONNREFUSED` to backend `localhost:8001`. + +**Findings/fix**: No backend process was listening on `:8001`; the frontend dev +server was already listening on `:3000` (node PID 17276). Started the backend on +`127.0.0.1:8001` with `ADMIN_PASSWORD=securePass123`, which reset the local +`admin@example.com` row. Added gitignored `frontend-nextjs/.env.local` with +`NEXT_PUBLIC_API_URL=http://localhost:8001`; updated +`backend/logs/bootstrap_admin_password.txt` to match the active local password. + +**Verification**: `POST http://127.0.0.1:8001/api/auth/login` returned an +access token. Browser-facing proxy `POST http://127.0.0.1:3000/api/auth/login` +also returned an access token. `GET http://127.0.0.1:3000/login?...` returned +200. From ebde2a507a2ce8ab4bae8ac70bca1f3daec5b639 Mon Sep 17 00:00:00 2001 From: ichandrasharma Date: Tue, 15 Sep 2026 21:11:14 +0530 Subject: [PATCH 2/6] feat(owner-dashboard): enhance data normalization and add live payload test --- AGENT_COORDINATION.md | 24 +++++++++++++++++++ frontend-nextjs/next.config.js | 4 ++++ frontend-nextjs/pages/dashboard/owner.tsx | 19 ++++++++++++--- .../tests/pages/dashboard-owner.test.tsx | 21 ++++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/AGENT_COORDINATION.md b/AGENT_COORDINATION.md index 14ebba9f1..9b7126aca 100644 --- a/AGENT_COORDINATION.md +++ b/AGENT_COORDINATION.md @@ -2137,3 +2137,27 @@ audited and landed (DSH's attachment round + my dedupe): grounded on mixed context and produced a wrong reverse-derivation (for a question I didn't ask) — pruned. The owner should ask attachment questions fresh; the evidence layer is verified. + +## 2026-09-15 — Codex: Owner Cockpit business-health 404 trace + +Touching `frontend-nextjs/next.config.js`, +`frontend-nextjs/pages/dashboard/owner.tsx`, and +`frontend-nextjs/tests/pages/dashboard-owner.test.tsx`. + +Runtime symptom from owner: `/dashboard/owner` shows "Failed to load dashboard +data"; Next logs `GET /api/business-health/priorities 404`. Backend has +`api.operational_routes` mounted at `/api/business-health/priorities`, so the +current evidence points at the Next rewrite layer missing the +`/api/business-health/*` proxy and owner page parsing not matching the live +`{data: {priorities: [...]}}` shape. Redis `localhost:6379` refusal appears to +be background webhook dequeue noise unless request-level evidence proves +otherwise. + +Finished: added the Next rewrite and normalized owner-page parsing for both +legacy `{data: [...]}` mocks and live `{data: {owner_advice, priorities}}`. +Verified route-level behavior: unauthenticated +`http://localhost:3000/api/business-health/priorities` now returns 401 (proxied +to the auth-gated backend) instead of Next 404; direct +`http://localhost:8000/api/business-health/priorities` also returns 401. +Focused Jest discovery finds `tests/pages/dashboard-owner.test.tsx`, but the +test run hung in shared MSW setup and was interrupted. diff --git a/frontend-nextjs/next.config.js b/frontend-nextjs/next.config.js index 7b61a0ff1..7c0f3be1a 100644 --- a/frontend-nextjs/next.config.js +++ b/frontend-nextjs/next.config.js @@ -196,6 +196,10 @@ const nextConfig = { source: "/api/analytics/:path*", destination: "http://127.0.0.1:8000/api/v1/analytics/:path*", }, + { + source: "/api/business-health/:path*", + destination: "http://127.0.0.1:8000/api/business-health/:path*", + }, { source: "/api/workflow-templates", destination: "http://127.0.0.1:8000/api/workflow-templates/", diff --git a/frontend-nextjs/pages/dashboard/owner.tsx b/frontend-nextjs/pages/dashboard/owner.tsx index eb4f3a05f..b8446c6f5 100644 --- a/frontend-nextjs/pages/dashboard/owner.tsx +++ b/frontend-nextjs/pages/dashboard/owner.tsx @@ -7,6 +7,18 @@ import { Button } from "@/components/ui/button"; import { RefreshCcw } from "lucide-react"; import { toast } from "sonner"; +const normalizePrioritiesPayload = (payload: any) => { + if (Array.isArray(payload)) return { ownerAdvice: null, priorities: payload }; + + const data = payload?.data ?? payload; + if (Array.isArray(data)) return { ownerAdvice: null, priorities: data }; + + return { + ownerAdvice: data?.owner_advice ?? null, + priorities: Array.isArray(data?.priorities) ? data.priorities : [], + }; +}; + export default function OwnerDashboard() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); @@ -23,14 +35,15 @@ export default function OwnerDashboard() { return; } const json = await res.json(); - const items = Array.isArray(json) ? json : (json?.data ?? []); + const { ownerAdvice, priorities: items } = normalizePrioritiesPayload(json); setData({ metrics: null, briefing: { owner_advice: - items.length > 0 + ownerAdvice ?? + (items.length > 0 ? `You have ${items.length} prioritized action${items.length > 1 ? "s" : ""} today.` - : "No open priorities right now.", + : "No open priorities right now."), priorities: items, }, }); diff --git a/frontend-nextjs/tests/pages/dashboard-owner.test.tsx b/frontend-nextjs/tests/pages/dashboard-owner.test.tsx index 2afc0b89c..c191e413e 100644 --- a/frontend-nextjs/tests/pages/dashboard-owner.test.tsx +++ b/frontend-nextjs/tests/pages/dashboard-owner.test.tsx @@ -43,6 +43,16 @@ const PAYLOAD = { ], }; +const LIVE_PAYLOAD = { + success: true, + data: { + owner_advice: "Focus on collections to stabilize cash flow.", + priorities: [ + { id: "p1", type: "GROWTH", title: "Call Acme", description: "Renewal call", priority: "HIGH", action_link: "/sales" }, + ], + }, +}; + describe("OwnerDashboard", () => { let mockFetch: jest.Mock; let consoleErrorSpy: jest.SpyInstance; @@ -75,6 +85,17 @@ describe("OwnerDashboard", () => { expect(screen.getByText("Open Simulator (Coming Soon)")).toBeDisabled(); }); + test("loads the live backend priorities envelope", async () => { + mockFetch.mockResolvedValue({ ok: true, json: async () => LIVE_PAYLOAD }); + render(); + + await waitFor(() => expect(screen.getByTestId("daily-briefing-card")).toBeInTheDocument()); + expect(latestBriefing).toEqual(expect.objectContaining({ + advice: "Focus on collections to stabilize cash flow.", + priorities: LIVE_PAYLOAD.data.priorities, + })); + }); + test("shows an error toast when the response is not ok", async () => { mockFetch.mockResolvedValue({ ok: false, json: async () => ({}) }); render(); From bb0c2b96230d0485c70f524dbbe750e17ec2b2bd Mon Sep 17 00:00:00 2001 From: ichandrasharma Date: Wed, 23 Sep 2026 20:33:45 +0530 Subject: [PATCH 3/6] fix(pdf-worker): update worker source path to legacy version --- frontend-nextjs/lib/pdf-worker-src.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-nextjs/lib/pdf-worker-src.ts b/frontend-nextjs/lib/pdf-worker-src.ts index 12acdedc1..36a025db8 100644 --- a/frontend-nextjs/lib/pdf-worker-src.ts +++ b/frontend-nextjs/lib/pdf-worker-src.ts @@ -8,5 +8,5 @@ * transform), where pdf.js degrades to its main-thread fake worker. */ export function pdfWorkerSrc(): string { - return new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString(); + return new URL("pdfjs-dist/legacy/build/pdf.worker.min.mjs", import.meta.url).toString(); } From 9c8b7c1af33402521ef0667b4ea352413282cb34 Mon Sep 17 00:00:00 2001 From: ichandrasharma Date: Mon, 28 Sep 2026 17:33:30 +0530 Subject: [PATCH 4/6] fix(next-env): update import path for routes type definitions --- frontend-nextjs/next-env.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-nextjs/next-env.d.ts b/frontend-nextjs/next-env.d.ts index cd1c4c7e9..7996d352f 100644 --- a/frontend-nextjs/next-env.d.ts +++ b/frontend-nextjs/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next-preview/dev/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. From 77c489d2160ba4cb8c785f3ea341545bbb65651e Mon Sep 17 00:00:00 2001 From: ichandrasharma Date: Fri, 9 Oct 2026 19:52:37 +0530 Subject: [PATCH 5/6] fix(chat-orchestrator): update intent mapping to handle unknown command types as agent requests fix(next-env): correct import path for route types in TypeScript environment --- backend/integrations/chat_orchestrator.py | 7 ++++--- frontend-nextjs/next-env.d.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/integrations/chat_orchestrator.py b/backend/integrations/chat_orchestrator.py index 0eb35ffad..92c3fc9dd 100644 --- a/backend/integrations/chat_orchestrator.py +++ b/backend/integrations/chat_orchestrator.py @@ -21561,9 +21561,10 @@ def _classify_intent(self, nlp_result) -> ChatIntent: CommandType.BUSINESS_HEALTH: ChatIntent.BUSINESS_HEALTH, CommandType.TRIGGER: ChatIntent.AUTOMATION_TRIGGER, CommandType.WORKFLOW_CREATION: ChatIntent.WORKFLOW_CREATION, + CommandType.UNKNOWN: ChatIntent.AGENT_REQUEST, } - return intent_mapping.get(command_type, ChatIntent.SEARCH_REQUEST) + return intent_mapping.get(command_type, ChatIntent.AGENT_REQUEST) def _fallback_intent_analysis(self, message: str) -> Dict[str, Any]: """Fallback intent analysis when NLP is unavailable""" @@ -21591,14 +21592,14 @@ def _fallback_intent_analysis(self, message: str) -> Dict[str, Any]: elif any(word in message_lower for word in ["deal", "lead", "pipeline", "sales", "prospect", "forecast"]): intent = ChatIntent.CRM else: - intent = ChatIntent.SEARCH_REQUEST + intent = ChatIntent.AGENT_REQUEST return { "primary_intent": intent, "confidence": 0.6, "entities": [], "platforms": [], - "command_type": "search" + "command_type": "agent" } def _continuation_decision( diff --git a/frontend-nextjs/next-env.d.ts b/frontend-nextjs/next-env.d.ts index b63ee6f98..7996d352f 100644 --- a/frontend-nextjs/next-env.d.ts +++ b/frontend-nextjs/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next-preview-crosssrc_fix_0929/dev/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. From 510e87df9622b580e88bed0c4cece27f0eccbc78 Mon Sep 17 00:00:00 2001 From: ichandrasharma Date: Fri, 9 Oct 2026 21:05:47 +0530 Subject: [PATCH 6/6] fix(chat-orchestrator): refine fallback logic for ComputerUseAgent to prevent overwriting successful responses --- backend/integrations/chat_orchestrator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/integrations/chat_orchestrator.py b/backend/integrations/chat_orchestrator.py index 92c3fc9dd..9a764f323 100644 --- a/backend/integrations/chat_orchestrator.py +++ b/backend/integrations/chat_orchestrator.py @@ -21809,9 +21809,11 @@ async def _route_to_features( logger.info(f"Feature handling complete. Handled: {handled}, Intent: {primary_intent}") - # Fallback to ComputerUseAgent if no specific feature handled it successfully - # OR if the intention was explicitly AGENT_REQUEST - if not handled or primary_intent == ChatIntent.AGENT_REQUEST: + # Fallback to ComputerUseAgent only when no feature handled the turn. + # A successful Atom/LLM agent response is already the user-facing answer; + # starting a background ComputerUse task here overwrites it with a + # generic "Task ID" status bubble. + if not handled: try: # Use the General Agent (ComputerUseAgent) for unhandled queries # Identity and size, not the goal text. The user's own words do