13 TDD tasks across two phases. Phase 1 (backend) ends with orders
matched automatically at intake plus a backlog sweep; Phase 2 surfaces
the paired quote line's note and attachments on both order pages.
Resolves the spec's two open questions: `after` is stable in
next/server on Next 16.2.6, and PocketBase date filters take
`.toISOString()`.
Two deviations from the spec, both noted in the plan: line pairing
hooks into the existing setOrderQuote rather than a new
linkQuoteToOrder, and the per-line context extends the existing
matched-attachments response rather than adding an endpoint.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Design for closing three gaps in the existing order↔quote matcher:
- The matcher only runs when an operator clicks it, so the ~85% of
orders that arrive against a quote stay unlinked. Adds a call from
createOrder plus a catch-up sweep for the backlog.
- order_items.quote_item is only written when an order is created
from a quote, so post-hoc links never pair lines. Adds persistence
for confident pairs.
- findMatchedQuoteItem re-guesses the pairing at render time using
exact/substring matching, so buyer notes and per-line attachments
silently vanish on any wording difference. Replaced with the
tokenised matcher already in the repo.
Fuzzy candidates are windowed to 90 days before the order's own date
(widening to 12 months only when nothing clears the threshold);
exact-identifier lookups stay unwindowed.
No PocketBase schema changes required.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Updated the search input handling to improve responsiveness by integrating a debounced search mechanism, reducing latency from 550 ms to approximately 300 ms.
- Added keyboard shortcut support for focusing the search box, enhancing accessibility and usability for frequent users.
- Improved the search placeholder to reflect all searchable fields, providing clearer guidance to operators.
- Introduced a clear-search button to streamline user interactions, allowing quick resets of the search input.
- Enhanced the display of search results with a live result count badge, providing immediate feedback on search outcomes.
These changes collectively enhance the search experience for operators, making it more intuitive and efficient.
Companion to the design spec at docs/superpowers/specs/. Covers all 15
implementation tasks (windowRange helper, aggregations, rep-activity
pagination, route handlers, tests, PWA manifest, mobile layout,
dashboard view with realtime + bottom sheet) plus the final
verification step.
Co-Authored-By: Claude <noreply@anthropic.com>
Introduces the `person_hint` field to the `EmailIntakePayload`, allowing the system to resolve the actual customer when a rep forwards an email. The `findOrCreateCustomer` function now prioritizes `person_hint` over the sender's email, enabling a more accurate attribution of quotes. This change includes a case-insensitive substring match with a token-drop fallback for multi-token names, ensuring better matching against existing customer records.
Additionally, new unit tests have been added to validate this functionality, covering various scenarios including token-drop behavior and ensuring the correct customer is linked when a rep forwards an RFQ.
Co-Authored-By: Claude <noreply@anthropic.com>
Gary (and any future rep) forwards inbound RFQs to a shared mailbox.
Today the customer linked to the resulting quote is the rep (or the
Unknown Sender sentinel), because the only resolution path is exact
email match — the from_email resolves to Gary, not the actual customer.
Add person_hint to EmailIntakePayload. The AI extraction layer reads
the subject / body / signature for the customer being quoted FOR and
fills person_hint. findOrCreateCustomer now walks three resolution
passes in order:
1. Exact email match (existing behaviour — direct RFQs unchanged)
2. person_hint resolution: case-insensitive substring on
customer.customer, with a companyHint tie-break when multiple
candidates exist
3. Existing sender-based create-new path (Gary wins, quoter
reassigns in the WFDASH UI)
MCP schema for quotes.create_from_email surfaces the new field with
doc explaining the rep-forwarded case. /api/v1/quotes/from-email
doc updated. AI Agent system prompt in the n8n workflow doc now
extracts person_hint with worked examples.
Also extends the mock filter parser to accept PB's bare ~ operator
(production code uses ~; the mock previously only accepted =~).
5 new unit tests + 2 integration tests for the new path.
Co-Authored-By: Claude <noreply@anthropic.com>
Hermes filed WFDASH-dev-ask-quotes-create.md on 2026-08-26 claiming
`quotes.create` doesn't exist. It does — registered at
src/app/api/mcp/route.ts:1131, REST at /api/v1/quotes/create, added
2026-08-15 in Phase G gap-fill, documented as Recipe 7 in
docs/agents/workflows.md. The agent's actual failure was discovery,
not a real gap.
Two doc-only changes to keep this from recurring:
1. Tool count 125 → 141 (live count), recipe count 7 → 9 (live count)
2. New prominent "Three quote-creation tools — don't confuse them"
section right under the intro listing all three paths
(quotes.create / quotes.ingest_from_email /
quotes.create_from_email) with the common failure mode explicitly
called out. Recipe 7 already covers the walk-in workflow;
this surfaces the contrast up front so the agent sees it during
session-startup instead of after it has already picked the wrong
tool.
No code change. No FEATURE-REQUESTS.md entry — the tool isn't a gap.
Co-Authored-By: Claude <noreply@anthropic.com>
Implementation plan for the spec committed in d87a007. Four tasks:
1. Scaffold 7 component tests (all fail initially)
2. Replace handleApprove + handleApprovePartial with lifted
SendQuoteModal + sendApprove; new 'Approve & send' button
3. Verify partial-row test passes from task 2 wiring
4. Manual smoke test against running PB
Lifts the detail-screen "Approve & send email" button behaviour onto
the pending-approvals list rows. Replaces the list's existing
two-step approve + drill-in flow with the existing combined
review-approve endpoint behind the same SendQuoteModal the detail
page already uses.
Out of scope: "approve without send" toggle in the modal, inline
markup-edit on a row.
Co-Authored-By: Claude <noreply@anthropic.com>
11 tasks covering schema, type, PATCH endpoint, three service
gate relaxations, PDF route bypass, PDF component rendering, UI
toggle on Quote Details card, MCP tool exposure, and an E2E
smoke test. TDD throughout with file:line citations to the
existing service tests as templates.
Co-Authored-By: Claude <noreply@anthropic.com>
Adds is_no_quote boolean to quotes collection so operators can send
an official decline letter on a quote the company cannot price.
Spec covers schema, service-layer gate relaxations, PDF rendering,
UI toggle placement, error edges, tests, and rollout.
Approach A (surgical flag relaxation) chosen over B/C during
brainstorming to keep v1 minimal and reversible.
Co-Authored-By: Claude <noreply@anthropic.com>
- Added support for deduplication of orders based on the `email_message_id`, preventing duplicate entries during email intake.
- Introduced the `displayContactName` utility to sanitize and format contact names, improving the display of order details by removing extraneous whitespace.
- Updated relevant order-related components to utilize the new utility for consistent contact name rendering.
- Enhanced tests to cover the new deduplication logic and the functionality of the `displayContactName` utility, ensuring robust behavior in various scenarios.
- Introduced a new toggle in the quotes and archive pages to allow users to include older quotes beyond the default 90-day cutoff.
- Updated the search parameters in the quotes and archive APIs to handle the new `includeOlder` flag, enabling full history searches.
- Enhanced the user interface to reflect the current search scope, providing clear feedback on whether the search is limited to recent quotes or includes the full archive.
- Adjusted the quotes search service to support the new functionality, ensuring efficient retrieval of older quotes when requested.
- Added relevant tests to verify the correct behavior of the new search feature and its integration with existing functionality.
- Updated the TV dashboard to include a new section for driver stops, displaying active deliveries and pickups with GPS coordinates.
- Refactored the dashboard data structure to incorporate year-over-year performance metrics alongside existing monthly and weekly stats.
- Replaced the supplier map with a driver stops map for improved clarity on driver activities.
- Enhanced the user performance metrics to include detailed counts for quotes and orders processed by each representative.
- Removed the obsolete supplier map component to streamline the dashboard's functionality.
- Updated the `GET /api/v1/orders` endpoint to support additional query parameters including `customer`, `createdAfter`, `createdBefore`, and `status`, allowing for more granular order filtering.
- Implemented logic to resolve customer IDs from names and aggregate order items by their statuses for improved data retrieval.
- Introduced new helper functions in `orders-service.ts` for fetching order statistics and daily summaries, enhancing reporting capabilities.
- Added comprehensive documentation for the new query parameters and their usage in the API documentation.
- Improved error handling for invalid customer and status inputs, ensuring clearer feedback for API consumers.
- Updated the `quotes.submit` tool to allow submission of quotes with unpriced items by introducing a `partial: true` flag, transitioning the quote to `partial_approval_pending` instead of `approval_pending`.
- Enhanced the response structure of `submitQuote` to include `previousStatus`, `submittedAt`, and `targetStatus`, providing better context for the agent.
- Improved error handling in the `sendQuoteEmail` function to surface detailed readiness issues when a PDF cannot be generated, allowing operators to address specific gaps in quote items.
- Regenerated API documentation in `docs/api-mcp-layer.md` to reflect these changes, ensuring accuracy and clarity in tool descriptions.
- Added comprehensive tests to validate the new functionality and error handling improvements.
- Introduced structured error handling for MCP upstream fetches, distinguishing between network errors (`-32010`) and upstream errors (`-32011`). This allows the agent to provide more informative feedback based on the type of failure encountered.
- Updated the `fetchUpstreamJson` function to throw `McpUpstreamError` with detailed error data, including hints and next actions for specific tools.
- Enhanced the `TOOL_HINTS` mapping to provide tool-specific guidance for handling errors, improving the agent's ability to respond to various failure scenarios.
- Added comprehensive unit tests to validate the new error handling logic and ensure correct behavior across different error cases.
- Updated documentation in `docs/agents/hermes-skill.md` to include a new section on structured MCP errors, detailing the error codes and their meanings.
- Added a new `quotes.submit` tool that transitions a quote from `new` to `approval_pending` once all line items are priced. This tool ensures that only fully priced quotes can be submitted for approval, enhancing the integrity of the approval process.
- Updated the API documentation in `docs/api-mcp-layer.md` to include the new `quotes.submit` tool and its usage details.
- Enhanced the `quotes` status enum in `docs/agents/hermes-skill.md` to reflect the new transition and its implications.
- Regenerated documentation to ensure accuracy, increasing the total tool count from 126 to 127.
- Added comprehensive tests for the `submitQuote` function to cover various scenarios, including idempotency and error handling for unpriced items.
- Introduced a new `quotes.create` tool for creating quotes from scratch without an inbound email, allowing operators to generate quotes directly from the dashboard.
- Updated `customers.list` to support filtering by representative using either a 15-char PB user ID or a case-insensitive name/email match.
- Enhanced API documentation in `docs/api-mcp-layer.md` to reflect the addition of the new quote creation tool and updated customer filtering capabilities.
- Regenerated documentation to ensure accuracy, increasing the total tool count from 125 to 126.
- Updated `docs/api-mcp-layer.md` to reflect the current state of the API, including new endpoints and tools.
- Added `category` field to `QUOTE_ITEM_PATCH_FIELDS` and `ORDER_ITEM_PATCH_FIELDS` to support item categorization.
- Introduced 22 new MCP tools to cover previously missing REST functionalities, increasing the total tool count from 103 to 125.
- Improved descriptions for several existing tools to clarify their usage and parameters.
- Regenerated the API documentation to ensure accuracy and completeness.
Add full purchase order agent tooling and supporting changes:
- Add server-side purchase-order-agent-service for scanning both stock and customer POs, with complete test coverage
- Add inline SKU and supplier SKU editing flows to stock order detail pages
- Update MCP API route to support new PO agent tools (purchase_orders.scan, diff, record_diff_report) and stock_purchase_items.list
- Fix flaky CollectionPoolPage tests by wrapping state-dependent assertions in waitFor
- Refactor CollectionPoolPage auto-collapse logic to avoid react-hooks lint trap and run exactly once on initial load
- Delete temporary .tmp-inspect-pool.mjs development script
Add full PIN-protected TV dashboard stack including auth, redirects, map view, APIs, and server services.
Also include these critical refinements:
- Overhaul PO number generation to use per-company monthly sequences
- Rework quote rejection to bounce quotes back to operator queues instead of marking them terminal
- Add post_processing order tab group for clearer workflow visibility
- Fix collection pool tooltip positioning, overflow clipping, and default collapsed state
- Refactor customer list API, clean up unused form props, and fix item intel popover target ID handling
- Add comprehensive tests for new components and update existing test expectations
This commit adds a full unauthenticated PWA for in-store retail order taking:
- Dedicated `/new-order` route with complete order form, customer/company picker
- Public `/api/counter/*` endpoints for search, order creation, and photo uploads
- Photo capture and gallery selection with 10-photo per order limit
- Offline caching via dedicated service worker and app manifest
- Shortcut redirect at `/counter` for quick installation
- Comprehensive setup and usage documentation in `docs/counter-pwa.md`
- Minor cleanup to root layout metadata and service worker registration
- Small layout fix for collection pool row text truncation
Orders submitted via the PWA appear immediately in the main CRM's New tab, and the app is designed for trusted office kiosk phones without requiring user login.
This commit adds several key features, improvements, and cleanups across the codebase:
- Add `order_items.confirm_collected` MCP/REST endpoint to mark order items as collected without requiring driver assignment
- Add standalone order creation and order split APIs for flexible order management
- Update order list sort to oldest-first to align with user workflow of working through oldest orders first
- Improve order search to show cross-tab matches and display source tab indicators on search results
- Add customer name similarity check to warn about mismatched QuickBooks customers during invoice creation
- Remove supplier name column from delivery note PDFs and clean up related data passing across delivery note routes
- Add validation and debug logging to ItemIntelPopover for missing item ID on apply actions
- Remove unused OrderItemContextPopoverTrigger component from order detail page
- Add delivery note regeneration script and update test suites for new and existing functionality
- Update documentation and add test coverage for the new collection confirm tool
Implementation plan for the spec at
docs/superpowers/specs/2026-08-07-order-item-context-block-design.md.
Tasks: backend service skeleton + impl + tests, /api/v1/.../context
endpoint + tests, OrderItemContextPanel + tests,
OrderItemContextPopoverTrigger + tests, sprint modal wire-in, orders
page wire-in, full test suite + build smoke.
Each task follows a TDD cycle: write failing test, run to confirm,
implement minimal code, run to confirm pass, commit.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Replaces the AI Insights section in order-sprint-process-modal with a
deterministic PocketBase-derived context block (last quote, last order,
last invoiced, stock). Same backend exposed as a popover trigger on
the orders detail page, replacing the existing AI-history ⓘ there.
Backend: new src/lib/server/order-item-context-service.ts +
GET /api/v1/order-items/[id]/context. Reuses pure helpers from
item-history-service (normaliseSkuForHistory, findBestDescriptionMatch,
aggregateSuppliers, computeCheapest).
UI: new <OrderItemContextPanel/> (inline expandable for the sprint
modal) and <OrderItemContextPopoverTrigger/> (ⓘ popover for orders
page). Apply = cost + supplier only; selling stays locked to the order.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Ship full split-invoice stock purchase order workflow:
- Add 5 new MCP tools for per-line stock purchase item management and catalogue updates
- Add idempotent database migration adding sku, unit, and supplier_sku fields to stock_purchase_items
- Implement service layers for all new operations, including auto-closing the parent PO when all lines are fully collected
- Add complete test coverage for new services and API routes
- Update all relevant documentation including MCP API specs, agent instructions, and feature request logs
Captures the full timeline of the 2026-08-04 incident where WFDASH
/api/mcp silently failed every spec-compliant MCP client's handshake
because the route didn't handle the mandatory 'initialize' method.
Includes:
- Symptom (Hermes log lines + WebUI '0 tools' display)
- Root cause (HTTP 404 on initialize → client terminates session)
- Fix summary (the three new handlers, with the critical 'don't use
the content envelope for initialize' gotcha)
- Verification recipe (curl against the live endpoint)
- Lessons to apply to other JSON-RPC endpoints we might add later
(initialize is mandatory; don't reuse the tools/call envelope;
HTTP 404 is a signal the endpoint isn't MCP at all)
Co-authored-by: Orca <help@stably.ai>
5 tasks: stock-items service helper, two PDF document components +
render helpers, two GET endpoints, UI changes (wrap + buttons).
TDD per task with test-first steps. Final task is full-repo
verification + manual smoke checklist.
Co-authored-by: Orca <help@stably.ai>
Two small additions to /stock-orders:
- Wrap long text in Number + Supplier columns
- Two PDF download buttons (Stocktake PDF, Orders PDF)
Both PDFs always include all rows, ignore the active status
filter and pagination. No persistence — throwaway reports.
Design reviewed: covers architecture, data model, API contract,
error handling, testing, and manual smoke. No new PB schema,
no new types.
Co-authored-by: Orca <help@stably.ai>
Six-task TDD plan to widen listStockPurchases with ordered_value +
received_value per row, expose it via a new v1 list route, migrate
the /stock-orders page from a client component reading PB directly
to a Server Component + sibling client table component, and move the
existing 7 page tests + add an 8th.
Co-authored-by: Orca <help@stably.ai>
Add an Approved design doc for the /stock-orders list table: two new
currency columns (Ordered, Received) showing sum(line.quantity *
line.cost_price) and sum(line.quantity_received * line.cost_price) per
stock purchase. Migrates the page from client-side direct PB read to
the service layer per AGENTS.md.
Co-authored-by: Orca <help@stably.ai>
Six tasks: service field, service filter, card visual, page wiring,
route smoke test, full verification. All TDD with frequent commits.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Mail-failed POs currently vanish from every buyer-tasks tab because
the po_draft and po_sent filters both exclude the 'mail_failed' status.
This adds a focused design that surfaces them in place inside PO Draft
with a red warning row + 'Resend' button that re-opens the shared
SendPoModal.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Removes the Adjust Quantity modal, surfaces invoice photos in a per-PO
strip, exposes inline-editable cost prices, and migrates the page to a
thin service layer (listCollectedItems, updateOrderItemCost,
confirmOrderItemsForInvoicing) with three new /api/v1 routes. Cost edits
are audited in the existing notes feed as category=cost entries; confirm
is one PocketBase batch.
Co-authored-by: Orca <help@stably.ai>
12-task TDD plan covering the service module, four API routes,
the modal component (built incrementally across 4 tasks), and the
page-hook. Each task ends with a commit; spec gaps surfaced during
self-review already merged into task content.
Co-authored-by: Orca <help@stably.ai>
Adds spec for the new item-first quick-draft modal on /stock-orders:
item-first stock-order entry, accumulates per supplier into draft POs,
reuses existing Send/Receive flow. No schema changes.
Co-authored-by: Orca <help@stably.ai>