Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,8 @@ next-env.d.ts
*.lcov
.next/
.venv/

# playwright auth state
/tests/playwright/.auth/
/playwright-report/
/test-results/
6 changes: 6 additions & 0 deletions .opencode/opencode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://opencode.ai/config.json",
"plugin": [
".opencode/plugins/graphify.js"
]
}
22 changes: 22 additions & 0 deletions .opencode/plugins/graphify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// graphify OpenCode plugin
// Injects a knowledge graph reminder before bash tool calls when the graph exists.
import { existsSync } from "fs";
import { join } from "path";

export const GraphifyPlugin = async ({ directory }) => {
let reminded = false;

return {
"tool.execute.before": async (input, output) => {
if (reminded) return;
if (!existsSync(join(directory, "graphify-out", "graph.json"))) return;

if (input.tool === "bash") {
output.args.command =
'echo "[graphify] Knowledge graph available. Read graphify-out/GRAPH_REPORT.md for god nodes and architecture context before searching files." && ' +
output.args.command;
reminded = true;
}
},
};
};
37 changes: 37 additions & 0 deletions .tmp/tasks/supportpilot-phase1/subtask_01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"id": "supportpilot-phase1-01",
"seq": "01",
"title": "Support Schema Migration — additive SQL + TDD tests",
"status": "pending",
"depends_on": [],
"parallel": true,
"suggested_agent": "CoderAgent",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/agent-core/migrations/005_add_pricing_flag_columns.sql",
"apps/agent-core/tests/conftest.py",
"apps/agent-core/src/db.py",
"apps/agent-core/src/models.py"
],
"acceptance_criteria": [
"TDD: test file written BEFORE migration SQL",
"File apps/agent-core/migrations/006_add_support_tables.sql exists",
"SupportConversation table: id UUID PK, title TEXT, status TEXT DEFAULT 'open', user_id UUID FK→users, salesforce_case_id TEXT, created_at/updated_at TIMESTAMPTZ",
"CaseReference table: id UUID PK, conversation_id UUID FK→SupportConversation, salesforce_case_id TEXT NOT NULL, case_number TEXT, subject TEXT, status TEXT, priority TEXT, owner TEXT, account_id TEXT, contact_id TEXT, last_synced_at TIMESTAMPTZ",
"EscalationRequest table: id UUID PK, case_id UUID FK→CaseReference, reason TEXT NOT NULL, requested_action TEXT, status TEXT DEFAULT 'pending', requested_by UUID FK→users, decided_by UUID, decision TEXT, decided_at TIMESTAMPTZ, created_at TIMESTAMPTZ",
"KnowledgeArticle table: id UUID PK, title TEXT NOT NULL, content TEXT NOT NULL, category TEXT, salesforce_article_id TEXT, embedding vector(1536), created_at TIMESTAMPTZ",
"SlaPolicy table: id UUID PK, name TEXT, priority TEXT, response_hours INT, resolution_hours INT, created_at TIMESTAMPTZ",
"Test covers: all tables exist after migration, column types and constraints, FK relationships, insert+read from each table, rollback behavior",
"All pytest tests pass — zero existing functionality changes",
"SQL follows same style as 005 migration (COMMENT ON, IF NOT EXISTS)"
],
"deliverables": [
"apps/agent-core/migrations/006_add_support_tables.sql",
"apps/agent-core/tests/test_support_migration.py"
],
"bounded_context": "support-infrastructure",
"module": "@agent-core/migrations"
}
46 changes: 46 additions & 0 deletions .tmp/tasks/supportpilot-phase1/subtask_02.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"id": "supportpilot-phase1-02",
"seq": "02",
"title": "Mock Salesforce Client — Python package with 9 methods + tests",
"status": "completed",
"agent_id": "coder-agent",
"started_at": "2026-05-28T00:00:00Z",
"completed_at": "2026-05-28T00:00:00Z",
"depends_on": [],
"parallel": true,
"suggested_agent": "CoderAgent",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/agent-core/src/tools.py",
"apps/agent-core/src/__init__.py",
"apps/agent-core/tests/conftest.py"
],
"acceptance_criteria": [
"TDD: test file written BEFORE implementation",
"Package apps/agent-core/src/salesforce/ exists with __init__.py exporting MockSalesforceClient",
"apps/agent-core/src/salesforce/client.py contains MockSalesforceClient class",
"search_cases(query, filters) → returns list of case dicts with realistic mock data",
"get_case_details(case_id) → returns single case dict with all expected fields",
"get_customer_context(account_id) → returns account + contact info dict",
"search_knowledge_base(query) → returns KB article list with content excerpts",
"search_similar_tickets(query) → returns past case list with resolution info",
"draft_reply(case_id, context) → returns realistic draft reply string (not empty)",
"create_case(subject, description, priority, account_id) → returns new case with generated ID",
"update_case(case_id, fields) → returns updated case with modified fields",
"escalate_case(case_id, reason) → returns escalation status dict",
"Each method accepts mode parameter: 'mock' | 'live' for future real SF integration",
"Class constructor accepts optional api_key, instance_url for future live mode",
"Tests: all 9 methods return correct response structures, mock data realism, mode switching, error handling (bad case_id returns error), async operation",
"All pytest tests pass — zero existing functionality changes"
],
"deliverables": [
"apps/agent-core/src/salesforce/__init__.py",
"apps/agent-core/src/salesforce/client.py",
"apps/agent-core/tests/test_salesforce_client.py"
],
"bounded_context": "support-infrastructure",
"module": "@agent-core/salesforce"
}
46 changes: 46 additions & 0 deletions .tmp/tasks/supportpilot-phase1/subtask_03.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"id": "supportpilot-phase1-03",
"seq": "03",
"title": "Support Role Mapping — extend RBAC, JWT, and middleware for support routes",
"status": "completed",
"agent_id": "coder-agent",
"started_at": "2026-05-28T00:00:00Z",
"completed_at": "2026-05-28T00:00:00Z",
"depends_on": [],
"parallel": true,
"suggested_agent": "CoderAgent",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/web/lib/auth/rbac.ts",
"apps/web/lib/auth/jwt.ts",
"apps/web/middleware.ts",
"apps/web/lib/auth/index.ts"
],
"acceptance_criteria": [
"TDD: test file written BEFORE implementation",
"rbac.ts: SupportRole type added: 'SUPPORT_AGENT' | 'TEAM_LEAD' | 'SUPPORT_OPS' | 'ADMIN'",
"rbac.ts: Role hierarchy: SUPPORT_AGENT < TEAM_LEAD < SUPPORT_OPS < ADMIN",
"rbac.ts: Old B2B roles preserved (EMPLOYEE, MANAGER, FINANCE, ADMIN) — backward compatible",
"rbac.ts: SUPPORT_ROUTES map with correct access per route: /support (4 roles), /team-lead (TEAM_LEAD, ADMIN), /support-ops (SUPPORT_OPS, ADMIN), /admin (ADMIN)",
"rbac.ts: checkSupportRouteAccess(role, path) function exported — parallel to existing checkRouteAccess",
"rbac.ts: New role constants and route rules exported",
"jwt.ts: TokenPayload extended with optional orgId?: string and sfOrgMapping?: string",
"jwt.ts: No changes to signToken or verifyToken logic",
"middleware.ts: /support/*, /team-lead/*, /support-ops/* added to route matcher",
"middleware.ts: Route check tries checkSupportRouteAccess first, falls back to checkRouteAccess for procurement routes",
"middleware.ts: x-sf-org header injected alongside x-role, x-user-id, x-department-id",
"Tests: SupportRole hierarchy, route access per role, backward compatibility with old roles, checkSupportRouteAccess edge cases",
"All vitest tests pass — zero existing functionality changes"
],
"deliverables": [
"apps/web/lib/auth/rbac.ts (modified)",
"apps/web/lib/auth/jwt.ts (modified)",
"apps/web/middleware.ts (modified)",
"apps/web/__tests__/lib/auth/rbac-support.test.ts"
],
"bounded_context": "support-infrastructure",
"module": "@web/auth"
}
48 changes: 48 additions & 0 deletions .tmp/tasks/supportpilot-phase1/subtask_04.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"id": "supportpilot-phase1-04",
"seq": "04",
"title": "/support Route — support workspace page with layout extraction",
"status": "completed",
"agent_id": "coder-agent",
"started_at": "2026-05-28T00:00:00Z",
"completed_at": "2026-05-28T00:00:00Z",
"depends_on": [],
"parallel": true,
"suggested_agent": "OpenFrontendSpecialist",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md",
".opencode/context/ui/web/ui-styling-standards.md",
".opencode/context/core/workflows/design-iteration-overview.md"
],
"reference_files": [
"apps/web/app/(chat)/page.tsx",
"apps/web/components/shell/Shell.tsx",
"apps/web/components/shell/Rail.tsx",
"apps/web/app/(admin)/layout.tsx",
"apps/web/app/api/agent/route.ts"
],
"acceptance_criteria": [
"apps/web/app/(chat)/layout.tsx created (extracted from existing (chat)/page.tsx pattern)",
"apps/web/app/(chat)/support/page.tsx created as 'use client' component",
"Header shows 'SupportPilot' with role badge (fetched from /api/agent/session)",
"Placeholder sections rendered: 'Case Search', 'Customer Context', 'Reply Draft'",
"Uses existing Shell component and Rail component",
"Fetches user info from /api/agent/session API endpoint",
"Handles loading state (skeleton/spinner while fetching session)",
"Handles error state (error message if session fetch fails)",
"Handles empty state (no cases yet messaging)",
"Responsive layout using Tailwind (matches existing pattern from chat page)",
"Navigates between 'Procurement Chat' and 'Support Workspace' via tab/links in (chat)/page.tsx",
"Existing (chat)/page.tsx navigation tab updated with working link to /support",
"All TypeScript compiles with no errors (tsc --noEmit passes)",
"Zero existing functionality changes in procurement chat"
],
"deliverables": [
"apps/web/app/(chat)/layout.tsx (new, extracted from page)",
"apps/web/app/(chat)/support/page.tsx (new)",
"apps/web/app/(chat)/page.tsx (modified — add navigation tab)"
],
"bounded_context": "support-infrastructure",
"module": "@web/app"
}
30 changes: 30 additions & 0 deletions .tmp/tasks/supportpilot-phase1/task.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"id": "supportpilot-phase1",
"name": "SupportPilot Phase 1 — Scaffold",
"status": "active",
"objective": "Set up support infrastructure alongside existing procurement code: additive SQL migration, mock Salesforce client, support RBAC roles, and a /support route workspace",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/web/lib/auth/rbac.ts",
"apps/web/lib/auth/jwt.ts",
"apps/web/middleware.ts",
"apps/web/app/(chat)/page.tsx",
"apps/web/components/shell/Shell.tsx",
"apps/web/components/shell/Rail.tsx",
"apps/agent-core/migrations/005_add_pricing_flag_columns.sql",
"apps/agent-core/tests/conftest.py"
],
"exit_criteria": [
"All 5 support tables exist after migration with correct FKs",
"MockSalesforceClient returns realistic data for all 9 methods",
"Support roles (SUPPORT_AGENT, TEAM_LEAD, SUPPORT_OPS, ADMIN) enforceable in middleware",
"Backward compatibility with existing B2B procurement roles verified",
"/support route renders support workspace with Shell/Rail, loading/error/empty states"
],
"subtask_count": 4,
"completed_count": 0,
"created_at": "2026-05-28T14:00:00Z"
}
50 changes: 50 additions & 0 deletions .tmp/tasks/supportpilot-phase2/subtask_01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"id": "supportpilot-phase2-01",
"seq": "01",
"title": "Create support tools Python module with all 9 @tool functions",
"status": "completed",
"agent_id": "coder-agent",
"started_at": "2026-05-28T00:00:00Z"
"depends_on": [],
"parallel": false,
"suggested_agent": "CoderAgent",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/agent-core/src/tools.py",
"apps/agent-core/src/salesforce/client.py",
"apps/agent-core/src/salesforce/__init__.py"
],
"acceptance_criteria": [
"apps/agent-core/src/support/__init__.py exists and exports SUPPORT_TOOLS list and all 9 tool functions",
"apps/agent-core/src/support/tools.py contains exactly 9 @tool functions in priority order",
"Each tool uses Pydantic input schema + instructor-extracted output + MockSalesforceClient call + GenUI __ui__ payload",
"Priority order enforced: 1.search_salesforce_cases → 2.get_case_details → 3.get_customer_context → 4.search_knowledge_base → 5.search_similar_tickets → 6.draft_case_reply → 7.create_case → 8.update_case → 9.escalate_case",
"Each tool returns JSON string with structured data AND __ui__ key matching the GenUI contract",
"__ui__ payload names and props match the specified contract table exactly",
"draft_case_reply uses instructor + Pydantic for structured output generation",
"escalate_case includes HITL confirmation step and role-check",
"SUPPORT_TOOLS list exported and importable from apps/agent-core/src/support/__init__.py",
"Tools can be imported without side effects (no top-level module execution)"
],
"deliverables": [
"apps/agent-core/src/support/__init__.py",
"apps/agent-core/src/support/tools.py"
],
"bounded_context": "customer-support",
"module": "apps/agent-core/src/support",
"contracts": [
{
"type": "interface",
"name": "MockSalesforceClient",
"path": "apps/agent-core/src/salesforce/client.py",
"status": "implemented",
"description": "9 async methods corresponding to each @tool"
}
],
"design_components": [
"apps/agent-core/src/support/tools.py — design each tool following existing procurement tool patterns (Pydantic → client → GenUI)"
]
}
36 changes: 36 additions & 0 deletions .tmp/tasks/supportpilot-phase2/subtask_02.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"id": "supportpilot-phase2-02",
"seq": "02",
"title": "TDD test file for all 9 support tools",
"status": "pending",
"depends_on": ["01"],
"parallel": false,
"suggested_agent": "CoderAgent",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/agent-core/tests/conftest.py",
"apps/agent-core/src/salesforce/client.py",
"apps/agent-core/src/support/tools.py",
"apps/agent-core/tests/test_tools_tdd.py"
],
"acceptance_criteria": [
"apps/agent-core/tests/test_support_tools.py exists with tests for all 9 tools",
"Each tool has at least one positive test: creates MockSalesforceClient, calls the tool, verifies response structure",
"Each tool test verifies __ui__ payload content matches the GenUI contract (name + props shape)",
"Test error handling: bad input, missing case/account, invalid action, etc.",
"Test role-based access: SUPPORT_AGENT can search/knowledge-base, only TEAM_LEAD can escalate",
"Tests use the test_db_pool and tool_config fixtures from conftest.py",
"Tests are async and use pytest-asyncio",
"All tests pass: `python -m pytest apps/agent-core/tests/test_support_tools.py -v`",
"Test coverage includes edge cases (empty results, missing fields, invalid priorities)",
"Tests do NOT require real LLM or Salesforce — use MockSalesforceClient exclusively"
],
"deliverables": [
"apps/agent-core/tests/test_support_tools.py"
],
"bounded_context": "customer-support",
"module": "apps/agent-core/tests"
}
39 changes: 39 additions & 0 deletions .tmp/tasks/supportpilot-phase2/subtask_03.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"id": "supportpilot-phase2-03",
"seq": "03",
"title": "Graph integration — register SUPPORT_TOOLS, system prompt, role-based routing",
"status": "pending",
"depends_on": ["01", "02"],
"parallel": false,
"suggested_agent": "CoderAgent",
"context_files": [
".opencode/context/core/standards/code-quality.md",
".opencode/context/core/standards/security-patterns.md"
],
"reference_files": [
"apps/agent-core/src/dependencies.py",
"apps/agent-core/src/graph.py",
"apps/agent-core/src/tools.py",
"apps/agent-core/src/support/tools.py",
"apps/agent-core/src/support/__init__.py"
],
"acceptance_criteria": [
"apps/agent-core/src/dependencies.py updated: lifespan initializes MockSalesforceClient as singleton accessible via get_salesforce_client()",
"apps/agent-core/src/graph.py updated: imports SUPPORT_TOOLS from apps/agent-core/src/support/__init__.py",
"ToolNode in graph.py uses combined tool list (ALL_TOOLS + SUPPORT_TOOLS)",
"SupportPilot section added to SYSTEM_PROMPT_STATIC with descriptions for all 9 support tools",
"System prompt matches existing ProcureAI tool routing documentation style",
"apps/agent-core/src/tools.py get_tools_for_role() updated: SUPPORT_AGENT, TEAM_LEAD, SUPPORT_OPS roles return support tools",
"Role mapping: SUPPORT_AGENT gets read tools (1-5), TEAM_LEAD gets all 9, SUPPORT_OPS gets read + mutation (1-8), ADMIN gets all",
"Support tools are only available when session user has a support role — strict domain separation from procurement tools",
"Existing procurement tool behavior is NOT affected by changes",
"All existing tests still pass after integration changes"
],
"deliverables": [
"apps/agent-core/src/dependencies.py (modified)",
"apps/agent-core/src/graph.py (modified)",
"apps/agent-core/src/tools.py (modified)"
],
"bounded_context": "customer-support",
"module": "apps/agent-core/src"
}
Loading