v3.1.2508202671

Doc Flow AI

No description.

scaffolded GitHub Linear linked Product Status MVP

CI

Latest GitHub Actions on main. Raw payload is in the Terminal.

success success CI

Open run

Deploy

Compose status for dev. Raw status is in the Terminal.

Lifecycle

Manual registry state (prefer deploy/undeploy when possible). Not Product Status.

Template sync

Open/update a chore/sync-template PR for this project.

Terminal connecting
CI
{
  "state": "success",
  "status": "completed",
  "conclusion": "success",
  "workflow_name": "CI",
  "branch": "main",
  "head_sha": "cf17818fdcb2",
  "html_url": "https://github.com/NexOTica-GmbH/doc-flow-ai/actions/runs/32872281857",
  "updated_at": "2026-08-25T16:30:03Z",
  "run_number": 1
}
Deploy status
{
  "project": {
    "id": "7ba7aeef-4fd0-43c4-9341-b588e55279dd",
    "name": "Doc Flow AI",
    "slug": "doc-flow-ai",
    "description": "",
    "scope": "",
    "product_version": "0.0.1",
    "product_status": "MVP",
    "github_repo_url": "https://github.com/NexOTica-GmbH/doc-flow-ai",
    "linear_project_id": "db99ccb1-a86e-4da1-9bdb-be23414fac96",
    "github_webhook_id": "670371286",
    "linear_webhook_id": null,
    "host_port": null,
    "api_host_port": null,
    "lifecycle_state": "scaffolded",
    "mvp_scope_locked_at": null,
    "created_at": "2026-08-25T16:29:27.076252",
    "updated_at": "2026-08-25T16:33:07.758144"
  },
  "env": "dev",
  "host": "host.docker.internal",
  "path": "/var/www/nexotica/dev/doc-flow-ai",
  "state": "missing",
  "host_port": "",
  "api_host_port": "",
  "url": "",
  "direct_url": "",
  "api_direct_url": "",
  "compose_ps": "missing:/var/www/nexotica/dev/doc-flow-ai"
}
Last action · ok · 2026-08-25 16:33:07.758144
{
  "project": {
    "id": "7ba7aeef-4fd0-43c4-9341-b588e55279dd",
    "name": "Doc Flow AI",
    "slug": "doc-flow-ai",
    "description": "",
    "scope": "",
    "product_version": "0.0.1",
    "product_status": "MVP",
    "github_repo_url": "https://github.com/NexOTica-GmbH/doc-flow-ai",
    "linear_project_id": "db99ccb1-a86e-4da1-9bdb-be23414fac96",
    "github_webhook_id": "670371286",
    "linear_webhook_id": null,
    "host_port": null,
    "api_host_port": null,
    "lifecycle_state": "scaffolded",
    "mvp_scope_locked_at": null,
    "created_at": "2026-08-25T16:29:27.076252",
    "updated_at": "2026-08-25T16:33:07.749958"
  },
  "scope_chat_status": "open",
  "active": true,
  "locked": false,
  "mvp_scope_locked_at": null,
  "draft_stories": [
    {
      "work": "Health page",
      "role": "Front-end",
      "title": "Health page (Front-end)",
      "product_status": "MVP",
      "acceptance_criteria": [],
      "description": "## Story\n\nHealth page\n\n## Acceptance criteria\n\n- [ ] Health page is implemented for the Front-end slice.\n- [ ] Automated tests cover the happy path where applicable.\n\n## Source\n\nProduct Manager scope. Product Owner must not expand business features.\n"
    },
    {
      "work": "Health endpoint",
      "role": "Back-end",
      "title": "Health endpoint (Back-end)",
      "product_status": "MVP",
      "acceptance_criteria": [],
      "description": "## Story\n\nHealth endpoint\n\n## Acceptance criteria\n\n- [ ] Health endpoint is implemented for the Back-end slice.\n- [ ] Automated tests cover the happy path where applicable.\n\n## Source\n\nProduct Manager scope. Product Owner must not expand business features.\n"
    }
  ],
  "product_status": "MVP",
  "closed_at_status": null,
  "messages": [
    {
      "id": "7dfd61c9-739c-40f2-9b49-69b23fdb4ecf",
      "role": "pm",
      "body": "## System Architecture & Technical Specifications\r\n```\r\n                           +-------------------------------------------------------+\r\n                           |                    Next.js Fullstack                  |\r\n                           |  (App Router + Tailwind + shadcn/ui + TypeScript)     |\r\n                           +---------------------------+---------------------------+\r\n                                                       |\r\n                  +------------------------------------+-----------------------------------+\r\n                  |                                    |                                   |\r\n                  v                                    v                                   v\r\n        +-------------------+               +--------------------+               +-------------------+\r\n        | Ingestion Engine  |               | Consensus Engine   |               | Cloud & Storage   |\r\n        | - File Parsing    |               | - LLM Provider API |               | - Google Drive API|\r\n        |   (PDF/CSV/TXT/   |               |   (Gemini, OpenAI, |               |   (Service Account|\r\n        |    Images)        |               |    Grok Adapter)   |               |    Auth)          |\r\n        | - PDF Renamer     |               | - Multi-Round Loop |               | - SQLite Database |\r\n        +-------------------+               +--------------------+               +-------------------+\r\n\r\n```\r\n---\r\n## 1. Complete Feature Matrix\r\n### Ingestion & Processing Pipeline\r\n* **Multi-Format Ingestion:** Drag-and-drop / file picker on the landing page accepting `.pdf`, `.png`, `.jpg`, `.jpeg`, `.csv`, `.txt`, and `.md`.\r\n* **Universal Normalization:** Text/CSV/Image inputs are parsed into text representations and normalized into a standard PDF artifact for archiving.\r\n* **Smart Renaming Engine:** Generates target PDF file names following the strict pattern: `ddmmyyyy-sender-sequence.pdf` (e.g., `22082026-AcmeCorp-001.pdf`), extracting the sender and date via the AI consensus or falling back to user input.\r\n### Multi-LLM Consensus Engine (Extensible)\r\n* **Provider Abstraction Interface:** Standardized `BaseLLMProvider` contract (`generateResponse`, `streamResponse`, `modelName`) allowing zero-friction addition of new models (OpenAI, Gemini, Grok, Claude).\r\n* **Sequential Peer Review Loop (Option A):**\r\n* **Round 1:** Model A (e.g., Gemini 1.5 Pro) reads the raw document and produces an initial structured assessment and tag recommendations.\r\n* **Round 2:** Model B (e.g., OpenAI GPT-4o) critiques Model A's extraction, flags discrepancies, and refines key data points.\r\n* **Rounds 3\u201310 (Configurable):** Iterative refinement between models until both models signal consensus or the 10-round cap is reached.\r\n* **Synthesis Step:** A unified assessment report (Markdown format) is generated and delivered to the chat window.\r\n* **Tag Suggestion Mechanism:** Models return candidate tags based on document analysis; suggestions are displayed as clickable chips in the UI without modifying the database.\r\n### Tag & Metadata Management\r\n* **Dynamic User-Driven Tags:** Clean-slate tag system with zero hardcoded tags.\r\n* **Manual Tag Creation:** Dedicated \"Create Tag\" modal/button in the chat interface allowing custom tag creation on the fly.\r\n* **Tag Assignment:** Documents can hold multiple user-confirmed tags, stored relationally in SQLite.\r\n\r\n### Chat & Interactive Workspace\r\n\r\n* **ChatGPT/Gemini-Style UI:** Responsive interface featuring a collapsible left sidebar (recent uploads and conversations) and a central chat stream.\r\n* **Post-Assessment Interactivity:** User can ask follow-up questions, request specific recalculations, or instruct the models to re-evaluate sections.\r\n* **Assessment Preview:** Split-screen or toggle view to see the source document alongside the generated Markdown assessment.\r\n* **Session Reset / Logout:** Clears current active session state and resets the workspace to the landing state.\r\n### Google Drive & Database Persistence\r\n* **Headless Service Account Integration:** Authenticates automatically using a root-level `service_account.json` credential file to access a designated Drive folder.\r\n* **Database Archival:** Persists document metadata, UUIDs, full chat transcripts, tag relationships, and Markdown/PDF assessment reports in a local SQLite database.\r\n---\r\n## 2. Dependency & Stack Assessment\r\nThis stack is selected for optimal compatibility with **Cursor** (TypeScript end-to-end type safety, unified Next.js App Router, zero-boilerplate ORM).\r\n\r\n### Recommended Tech Stack\r\n\r\n* **Framework:** Next.js 14/15 (App Router, Server Actions, Route Handlers)\r\n* **Styling & Components:** Tailwind CSS + `shadcn/ui` + `lucide-react`\r\n* **Database & ORM:** SQLite via `@libsql/client` or `better-sqlite3` + `drizzle-orm` (lightweight, zero external server requirement)\r\n* **File & PDF Processing:** `pdf-parse`, `pdf-lib`, `papaparse`, `tesseract.js` (or LLM Vision API for OCR)\r\n\r\n### Core Dependencies & Environment Configuration\r\n\r\n| Package | Purpose | Version Spec |\r\n| --- | --- | --- |\r\n| `googleapis` | Google Drive API v3 Service Account Client | `^140.0.0` |\r\n| `@google/genai` | Google Gemini SDK | Latest |\r\n| `openai` | OpenAI & Grok (xAI API is OpenAI-compatible) | `^4.50.0` |\r\n| `drizzle-orm` / `drizzle-kit` | SQLite Database Schema & Query Builder | Latest |\r\n| `better-sqlite3` | Local database engine | `^9.0.0` |\r\n| `pdf-lib` | Client/Server PDF creation & metadata manipulation | `^1.17.1` |\r\n| `papaparse` | CSV data parsing | `^5.4.1` |\r\n| `zod` | Runtime validation for LLM structured outputs | `^3.23.0` |\r\n\r\n#### Environment Variables (`.env.local`)\r\n\r\n```env\r\n# AI Providers\r\nGEMINI_API_KEY=\"AIzaSy...\"\r\nOPENAI_API_KEY=\"sk-proj-...\"\r\nGROK_API_KEY=\"xai-...\"\r\nDEFAULT_MAX_DEBATE_ROUNDS=10\r\n\r\n# Google Drive Configuration\r\nGOOGLE_APPLICATION_CREDENTIALS=\"./service_account.json\"\r\nGOOGLE_DRIVE_FOLDER_ID=\"1A2B3C4D5E6F7G8H9I0J\"\r\n\r\n# Database\r\nDATABASE_URL=\"file:./data/app.db\"\r\n```\r\n---\r\n## 3. Database Schema Design (SQLite / Drizzle)\r\n\r\n```sql\r\n-- Documents Table\r\nCREATE TABLE documents (\r\n    id TEXT PRIMARY KEY, -- UUIDv4\r\n    original_filename TEXT NOT NULL,\r\n    gdrive_filename TEXT,\r\n    gdrive_file_id TEXT,\r\n    mime_type TEXT NOT NULL,\r\n    local_file_path TEXT NOT NULL,\r\n    sender TEXT,\r\n    sequence_number INTEGER,\r\n    status TEXT CHECK(status IN ('uploaded', 'analyzing', 'ready', 'exported', 'failed')) DEFAULT 'uploaded',\r\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\r\n    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\r\n);\r\n\r\n-- Tags Table (User-created only)\r\nCREATE TABLE tags (\r\n    id TEXT PRIMARY KEY, -- UUIDv4\r\n    name TEXT UNIQUE NOT NULL,\r\n    color TEXT DEFAULT '#3B82F6',\r\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\r\n);\r\n\r\n-- Document <-> Tags Junction Table\r\nCREATE TABLE document_tags (\r\n    document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,\r\n    tag_id TEXT NOT NULL REFERENCES tags(id) ON DELETE CASCADE,\r\n    PRIMARY KEY (document_id, tag_id)\r\n);\r\n\r\n-- Assessments Table\r\nCREATE TABLE assessments (\r\n    id TEXT PRIMARY KEY, -- UUIDv4\r\n    document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,\r\n    final_markdown TEXT NOT NULL,\r\n    debate_rounds_count INTEGER NOT NULL,\r\n    raw_debate_transcript TEXT, -- JSON Array of internal model exchanges\r\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\r\n);\r\n\r\n-- Chat Transcript Messages\r\nCREATE TABLE chat_messages (\r\n    id TEXT PRIMARY KEY, -- UUIDv4\r\n    document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,\r\n    sender_role TEXT CHECK(sender_role IN ('user', 'assistant', 'system', 'gemini', 'openai', 'grok')) NOT NULL,\r\n    content TEXT NOT NULL,\r\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\r\n);\r\n```\r\n---\r\n## 4. Extensible LLM Provider Interface\r\n\r\n```typescript\r\n// lib/llm/types.ts\r\nexport interface LLMMessage {\r\n  role: 'system' | 'user' | 'assistant';\r\n  content: string;\r\n}\r\n\r\nexport interface LLMResponse {\r\n  content: string;\r\n  suggestedTags?: string[];\r\n  metadata?: {\r\n    sender?: string;\r\n    date?: string;\r\n  };\r\n}\r\n\r\nexport interface BaseLLMProvider {\r\n  name: string;\r\n  analyzeDocument(content: string | Buffer, mimeType: string, prompt: string): Promise<LLMResponse>;\r\n  critiqueAssessment(documentContent: string, previousAssessment: string, roundNumber: number): Promise<LLMResponse>;\r\n  chat(messages: LLMMessage[]): Promise<string>;\r\n}\r\n\r\n```\r\n---\r\n## 5. Comprehensive User Stories Catalog\r\n### Epic 1: Document Upload & Ingestion\r\n* **US-1.1: Multi-Format Ingestion**\r\n* **As a** user,\r\n* **I want to** drag and drop or upload PDF, Image, CSV, TXT, or Markdown files on the landing page,\r\n* **So that** I can process any document regardless of its source format.\r\n* **Acceptance Criteria:**\r\n* Landing page shows a clean upload dropzone.\r\n* Supported file formats (`.pdf`, `.png`, `.jpg`, `.jpeg`, `.csv`, `.txt`, `.md`) are accepted; all others show an error toast.\r\n* File is assigned a unique UUID and stored in local temporary storage.\r\n* **US-1.2: Transition to Active Workspace**\r\n* **As a** user,\r\n* **I want to** be automatically transitioned to the chat workspace once a file is uploaded,\r\n* **So that** I can monitor the analysis and begin interacting immediately.\r\n* **Acceptance Criteria:**\r\n* Landing page smoothly transitions to the ChatGPT/Gemini-style dual-panel workspace upon upload completion.\r\n* Document status indicators update from \"Processing\" to \"Analyzing\" to \"Ready\".\r\n---\r\n### Epic 2: Multi-LLM Collaborative Review Engine\r\n* **US-2.1: Sequential Peer Review (Gemini & OpenAI)**\r\n* **As a** user,\r\n* **I want** Gemini and OpenAI to collaboratively review the document up to a maximum of 10 rounds,\r\n* **So that** I receive a highly accurate, audited assessment report.\r\n* **Acceptance Criteria:**\r\n* Model A generates initial extraction and summary.\r\n* Model B reviews Model A's output against the raw file content, pointing out corrections or omissions.\r\n* The process repeats sequentially until models reach agreement or hit 10 rounds maximum.\r\n* Final consolidated Markdown report is rendered in the main chat viewport.\r\n* **US-2.2: Third-Party Model Extensibility (Grok / Claude)**\r\n* **As a** developer/user,\r\n* **I want** the LLM engine to follow an abstracted interface,\r\n* **So that** I can plug in Grok (xAI) or other providers without rewriting the core workflow.\r\n* **Acceptance Criteria:**\r\n* Adding a new provider requires only implementing the `BaseLLMProvider` interface and registering it in a factory map.\r\n---\r\n### Epic 3: Tagging & Metadata Control\r\n* **US-3.1: Zero-Seed Dynamic Tag Creation**\r\n* **As a** user,\r\n* **I want to** create custom tags manually whenever needed with no predefined seed tags,\r\n* **So that** my taxonomy matches my personal organization requirements.\r\n* **Acceptance Criteria:**\r\n* Initial database contains 0 tags.\r\n* \"Create Tag\" button opens a quick modal with tag name and color selection.\r\n* Newly created tag is immediately available for document association.\r\n* **US-3.2: AI Tag Suggestions (Read-Only)**\r\n* **As a** user,\r\n* **I want to** see tag recommendations from the AI without them being auto-created,\r\n* **So that** I maintain complete control over my tag taxonomy.\r\n* **Acceptance Criteria:**\r\n* LLM consensus response includes suggested tags rendered as clickable chips.\r\n* Clicking a suggestion checks if the tag exists; if not, it prompts the user to confirm creation before applying.\r\n---\r\n### Epic 4: Interactive Chat & Post-Assessment\r\n* **US-4.1: Assessment Discussion**\r\n* **As a** user,\r\n* **I want to** ask follow-up questions about the assessment in the chat interface,\r\n* **So that** I can clarify specific clauses, values, or calculations.\r\n* **Acceptance Criteria:**\r\n* Chat input accepts questions and responds with context from both the document and consensus report.\r\n* Full message history is appended to `chat_messages` in the database.\r\n\r\n* **US-4.2: Recent Conversations & File Sidebar**\r\n* **As a** user,\r\n* **I want** a sidebar listing recent uploads and past conversations,\r\n* **So that** I can switch back to previous documents and review their state.\r\n* **Acceptance Criteria:**\r\n* Left sidebar displays chronological list of uploaded documents with assigned tags.\r\n* Clicking a historical item loads its chat transcript, assessment, and metadata.\r\n---\r\n### Epic 5: Google Drive Archival & Database Storage\r\n* **US-5.1: File Renaming & Standardized PDF Export**\r\n* **As a** user,\r\n* **I want** the uploaded file converted to PDF and renamed as `ddmmyyyy-sender-sequence.pdf`,\r\n* **So that** all stored documents have consistent, predictable file names.\r\n* **Acceptance Criteria:**\r\n* Non-PDF documents are converted to PDF format.\r\n* Sender name is extracted from AI metadata (or requested from user if missing).\r\n* Date format is strictly `ddmmyyyy`. Sequence number increments based on existing records in the database.\r\n\r\n* **US-5.2: Service Account Google Drive Upload**\r\n* **As a** system/user,\r\n* **I want** the renamed PDF uploaded to Google Drive via a local `service_account.json` file,\r\n* **So that** I do not have to perform interactive OAuth logins.\r\n* **Acceptance Criteria:**\r\n* Server loads `service_account.json` from the root directory.\r\n* File uploads to the specified Google Drive target folder.\r\n* Returned Google Drive File ID and web view link are recorded in the database.\r\n\r\n* **US-5.3: Database Transcript & Assessment Persistence**\r\n* **As a** user,\r\n* **I want** the original filename, generated report, and full chat transcript persisted in the database,\r\n* **So that** I have a permanent local audit trail.\r\n* **Acceptance Criteria:**\r\n* `assessments` and `chat_messages` tables are updated at the end of each session.\r\n* Database stores the original file name alongside the renamed Drive file name.",
      "seq": 1,
      "created_at": "2026-08-25T16:32:43.593951"
    },
    {
      "id": "de998a6e-fd4c-4709-baa1-bb059e951911",
      "role": "po",
      "body": "Thanks for the comprehensive overview, PM! This gives us a great foundation for Doc Flow AI.\n\nTo effectively define our MVP scope, especially considering our fixed **React frontend** and **Python Flask backend**, I need a bit more clarity on the initial product focus.\n\nCould you please help me with the following:\n\n1.  **Who is the primary user** for this MVP?\n2.  **What is the single most critical problem** this MVP aims to solve for them?\n3.  Based on that problem, which of the proposed Epics (Document Upload & Ingestion, Multi-LLM Collaborative Review Engine, Tagging & Metadata Control, Interactive Chat & Post-Assessment, Google Drive Archival & Database Storage) are **absolutely essential for the MVP**? Please indicate their priority.\n4.  What would be the **key acceptance criteria** for the MVP to be considered successful from this primary user's perspective?",
      "seq": 2,
      "created_at": "2026-08-25T16:33:07.743201"
    }
  ],
  "status": "open",
  "message": {
    "id": "de998a6e-fd4c-4709-baa1-bb059e951911",
    "role": "po",
    "body": "Thanks for the comprehensive overview, PM! This gives us a great foundation for Doc Flow AI.\n\nTo effectively define our MVP scope, especially considering our fixed **React frontend** and **Python Flask backend**, I need a bit more clarity on the initial product focus.\n\nCould you please help me with the following:\n\n1.  **Who is the primary user** for this MVP?\n2.  **What is the single most critical problem** this MVP aims to solve for them?\n3.  Based on that problem, which of the proposed Epics (Document Upload & Ingestion, Multi-LLM Collaborative Review Engine, Tagging & Metadata Control, Interactive Chat & Post-Assessment, Google Drive Archival & Database Storage) are **absolutely essential for the MVP**? Please indicate their priority.\n4.  What would be the **key acceptance criteria** for the MVP to be considered successful from this primary user's perspective?",
    "seq": 2
  },
  "providers": {
    "gemini": "ok",
    "openai": "ok",
    "mode": "merged_via_gemini"
  }
}