WFDASH-WEBAPP/.mavis/plans/plan.yaml
SJCoetz 33591959c2 feat: add quote email intake and atomic numbering
This commit implements the full inbound quote email processing workflow and atomic quote numbering:
- Add PocketBase collections for monthly atomic quote counters, email attachments, and threaded replies
- Add idempotent migration script to set up new collections and add deduplication field to existing quotes table
- Implement `/api/v1/quotes/next-number` endpoint for properly formatted Q-YYYY-MM-NNN quote numbers
- Add MCP tools for idempotent quote creation, reply threading, and message ID lookup
- Add end-to-end and concurrent smoke tests for pipeline validation
- Update TypeScript types for new quote-related entities
- Update project documentation and package.json scripts
- Mark quote email intake as complete in the parity backlog
- Add n8n v2 workflows for automated email monitoring and error alerts
2026-06-22 13:58:24 +02:00

204 lines
11 KiB
YAML

version: 1
plan:
name: 'WFDASH Quote Workflow — fix LLM, verify end-to-end'
max_concurrency: 2
max_consecutive_failures: 2
max_cycles: 6
auto_reject_retries: 1
verifier_config:
default_verifiers: [verifier]
audit_sample_rate: 0.0
tasks:
- id: fix-and-verify-llm-e2e
title: 'Fix LLM in active Quote Email Monitor workflow and prove end-to-end quote creation works'
prompt: |
# Context
You are fixing a production quote-creation pipeline for the WFDASH Next.js app.
Workspace root: `/Volumes/EXT/DEVELOPMENT/WFDASH_NEXTJS` (a real repo, do not delete files).
The pipeline lives in n8n on instance **wfsales_cooli**:
- base_url: `http://n8n-n65e89ippimn77mwlaijnl05.169.239.180.130.sslip.io`
- api_key: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0Zjc3MGRmMi1iZDJmLTQ0MzYtYjE1My1iMjcwMDRlZmM3YjYiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwianRpIjoiMDA5Y2Q0ZWUtMTU0NS00ZDZiLThkYzEtZTAyNTZlMWU3MzZmIiwiaWF0IjoxNzgxNjM1Njk5fQ.UJw-uIHDvXjAobBwpf8bd1xTZi5GUQvditfbNTrs19c`
Target PocketBase:
- base_url: `https://pocketbase-gnqc88suy8fqk6wyryjjdpvl.169.239.180.130.sslip.io`
- admin_email: `david.els1@outlook.com`
- admin_password: `1234567890`
Active workflow id: `eXSh623OjByIcip8`
Name: `WFDASH — Quote Email Monitor (v4 direct-to-PB)`
It has 54 nodes, is currently `active=true`, and writes to PB collections:
`quotes`, `quote_items`, `quote_attachments`, `quote_replies`, `quote_counters`,
`customers`, `companies`. The trigger is `IMAP Quote Mailbox` (n8n-nodes-base.emailReadImap).
# What is broken (already diagnosed)
Recent executions fail with: `NodeOperationError: Connection error.` at
`@n8n/n8n-nodes-langchain .../InformationExtractor.node.ts:303`.
The InformationExtractor calls an LLM via the `Minimax Chat Model` node
(type `@n8n/n8n-nodes-langchain.lmChatMinimax`, credential id `kn97KHCrkyTm3v2g`
named "MiniMax account", model `Minimax-M2.7`). The "Connection error" means
n8n cannot reach the LLM endpoint with that credential/model. The credential
is supposed to be wired through n8n's built-in Minimax auth.
18 of the last 50 executions failed with this pattern. The other 32 succeeded,
which suggests the credential sometimes works and sometimes does not — likely
a rate limit, transient API outage, or model-name routing issue on the
provider side. Investigate the credential configuration and the failure
pattern carefully.
# Goal
1. Diagnose the actual root cause of the LLM connection error.
2. Apply the minimal correct fix to workflow `eXSh623OjByIcip8` so the
LLM step succeeds deterministically.
3. Prove end-to-end: a real test email (or injected test data) results
in a quote in PocketBase with the PDF/csv/etc. attachment linked AND
AI-extracted `quote_items` rows.
4. Leave the workflow in a clean, working, active state. Do NOT create
a new copy; fix in place. Do NOT touch the 22 other inactive workflow
variants on the instance — the user will clean those up later.
# What "done" looks like
- Workflow `eXSh623OjByIcip8` updated in place and still active.
- One end-to-end run with a realistic test input succeeds:
* a `quotes` record exists with the right shape
* at least one `quote_attachments` row linked to that quote (when input has an attachment)
* at least one `quote_items` row linked to that quote with AI-extracted data
- You capture the execution id and the resulting PB record ids as evidence.
# How to approach this
Step 1 — Diagnose.
- Use the n8n API to fetch at least 3 different failed executions
(vary by error time) and look at the full error message, last node,
and any error metadata. The earlier sample showed only
"Connection error." — there may be more in `data.resultData.error.description`
or in the n8n logs.
- Inspect the Minimax credential in n8n (you cannot see the secret value
via API, but you can confirm the credential id is referenced correctly
on the LLM node, and check whether other workflows on the same instance
use a working Minimax credential you can compare against).
- Test the Minimax API directly with a small python or curl script using
any API key info you can find in the workspace, or the credential id as
a reference. If you can extract a working key from elsewhere in the
workspace (e.g. a `.env.local`, `scripts/`, or `pb_schema` directory),
use it to test the model `Minimax-M2.7` against the actual Minimax endpoint.
- State explicitly in your report: is the model name valid? Is the
credential actually configured? Is the endpoint reachable from this
n8n host? What did the API directly say when you called it?
Step 2 — Fix.
- Apply the minimal change. Likely candidates, in order of probability:
a) Wrong model name in the LLM node — fix to a known-good Minimax
model (e.g. `MiniMax-M2.7` if it actually exists, or whatever the
current valid public model is — verify against the live API).
b) Credential misconfiguration (wrong credential id, missing fields).
c) Network egress from the n8n host to the Minimax API.
d) Add fallback / retry behaviour if the failure mode is intermittent.
- You may add a Webhook or Manual trigger node in parallel with the
IMAP trigger to make the workflow testable, but keep the IMAP trigger
as the production entry point. Do not remove IMAP.
- Do NOT change unrelated nodes, schemas, or business logic. Touch only
what is necessary to make the LLM step succeed.
Step 3 — End-to-end test.
- Use one of:
* a Webhook trigger you added (POST a mock IMAP-shaped payload that
includes a small text body and a base64 attachment representing a
quote request),
* or, if a Webhook is not viable, the n8n manual execution API with
pinned input data on the IMAP node,
* or, as a last resort, send a real test email to the IMAP mailbox.
- The test input must include: a `from_email`, a `subject`, a `body_plain`
with at least one line item phrase (e.g. "Please quote 50x 20mm cable
ties"), and one attachment (a small PDF or text file) so the
attachment-linked-to-quote path is exercised.
- Wait for execution to complete (poll `/api/v1/executions/{id}`).
- Use the PocketBase API (auth as `david.els1@outlook.com`) to confirm:
* a new record in `quotes` was created,
* at least one record in `quote_attachments` references that quote id,
* at least one record in `quote_items` references that quote id with
non-empty `description`.
- Capture: workflow execution id, quote record id, attachment record id,
item record id.
Step 4 — Cleanup of test data.
- Delete the test quote, its items, its attachment, and any auto-created
customer/company that the test generated. Leave real production data
untouched.
# Constraints
- Use the n8n API for workflow reads/updates (do not ask the user to click).
Base URL and key are at the top of this prompt.
- Use the PocketBase API for the test verification. Auth as the admin.
- Do not commit any secrets into the repo. Do not edit `.env.local` or
any committed file with the PB password or the n8n key in it.
- Do not delete or archive any workflows. The 22 inactive variants stay.
- Do not modify files outside the workflow. The fix lives in n8n.
- If you hit a real blocker you cannot resolve in 2 attempts, stop, write
a clear `deliverable.md` describing the blocker with evidence, and exit.
Do not loop.
# Deliverable
Write `/Volumes/EXT/DEVELOPMENT/WFDASH_NEXTJS/.mavis/plans/fix-and-verify-llm-e2e.deliverable.md`
with:
- Root cause (one paragraph).
- What you changed in the workflow (node name + parameter diff).
- End-to-end evidence: execution id + PB record ids + a short note
describing what each record contains.
- Anything you noticed that the user should look at later (e.g. the
22 dead workflows, the schema field that looks risky, etc.) — keep
this short, just a "follow-ups" list.
assigned_to: coder
verified_by: verifier
verify_prompt: |
You are independently verifying that the WFDASH quote workflow is actually
working end-to-end after the fix. Do NOT just read the producer's
`deliverable.md` and rubber-stamp it. Re-derive the key claims.
Workflow id: `eXSh623OjByIcip8` on instance `wfsales_cooli`
- base_url: `http://n8n-n65e89ippimn77mwlaijnl05.169.239.180.130.sslip.io`
- api_key: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0Zjc3MGRmMi1iZDJmLTQ0MzYtYjE1My1iMjcwMDRlZmM3YjYiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwianRpIjoiMDA5Y2Q0ZWUtMTU0NS00ZDZiLThkYzEtZTAyNTZlMWU3MzZmIiwiaWF0IjoxNzgxNjM1Njk5fQ.UJw-uIHDvXjAobBwpf8bd1xTZi5GUQvditfbNTrs19c`
PocketBase:
- base_url: `https://pocketbase-gnqc88suy8fqk6wyryjjdpvl.169.239.180.130.sslip.io`
- admin_email: `david.els1@outlook.com`
- admin_password: `1234567890`
Checks (each must hold for PASS):
1. The active workflow `eXSh623OjByIcip8` exists, is `active=true`, and
the diff between the version the producer says they saved and the
current state is what they claim.
2. The InformationExtractor and LLM (`lmChatMinimax`) nodes are still
present and still wired together. The model name and credential id
on the LLM node are what the producer reports.
3. The producer's claimed end-to-end execution id completed with
`status=success` (or `finished=true`, no error). Open the execution
and confirm there is no error block.
4. In PocketBase, the producer's claimed `quotes` record id exists,
was created during the test window, and has a non-empty `quote_number`.
5. In PocketBase, at least one `quote_attachments` record references the
claimed `quotes` id (the attachment-linking path actually ran).
6. In PocketBase, at least one `quote_items` record references the
claimed `quotes` id with a non-empty `description` (the LLM
extraction actually produced something).
7. The test data the producer says they cleaned up is actually gone
(the test quote, its items, its attachment, and the auto-created
customer/company if any are no longer present in PB).
8. The 22 other inactive Quote Email Monitor workflow variants on the
instance are still present and untouched (count before/after — no
collateral damage).
If any check fails, return FAIL with the specific check that failed and
the evidence. If all 8 pass, return PASS with a one-line summary per
check. Do not invent evidence — if you cannot verify a check from the
APIs, say so and treat that as FAIL.
max_retries: 2