Commit graph

114 commits

Author SHA1 Message Date
64f8b71603 feat(tasks): add request parsing for generate-and-assign core module 2026-07-18 10:12:47 +00:00
d8aaea33e6 refactor(sync): export designation-matching helpers for reuse 2026-07-18 10:10:10 +00:00
fb3fe67164 chore: ignore .worktrees/ directory for isolated feature work
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 10:03:10 +00:00
6ab58dec68 docs: implementation plan for per-client generation + preview dialog
Bite-sized, TDD-ordered plan for docs/superpowers/specs/2026-07-18-task-generation-preview-and-per-client-design.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 09:21:20 +00:00
270c38ff19 docs: design for per-client task generation + preview-before-generate
Adds a clientId targeting mode and a dryRun flag to the admin
generate-and-assign tool, plus a confirmation dialog showing summary
counts before any tasks are actually created.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 02:19:48 +00:00
64ea7800ed fix(tasks): skip generating tasks with computed due dates in the past
auto-generate.ts and all three manual task-generation routes computed
due dates purely from a policy/group anchor date plus a template's
daysOffset, with no check against the current date. Surfaced when a
manual backfill for two clients created tasks anchored to an already-
expired policy term, producing due dates back in 2024.

Add isRelevantDueDate() and apply it at every task-creation call site
so no template-generated task is ever born already overdue.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 20:59:02 +00:00
e7da36e7e7 docs: capture in-progress design for task change log & restore feature
Paused mid-brainstorm at user request. Records the approved architecture
shape (DB-trigger-based change capture, run-scoped restore, hourly rollup
for oversight) and the open items to pick up on resume.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 18:46:02 +00:00
38365e97b5 fix(clients): Show Completed toggle did nothing for tasks older than 7 days
The default task fetch (/api/clients/[id]/tasks) already excludes
completed/cancelled/NA tasks older than a 7-day cutoff server-side. The
"Show Completed" button only filtered the in-memory task list, so if all
completed tasks were older than a week, toggling it revealed nothing —
they were never fetched.

Wire the toggle to re-fetch with archived=true (bypasses the cutoff) when
turning it on, and revert to the default filtered fetch when turning it
back off, so it doesn't leak dead-policy tasks into the non-completed view.
2026-07-17 15:35:45 +00:00
6a5006822b fix(setup-queue): surface dead-policy clients hidden behind badge count
The Manager nav badge, dashboard tile, and metrics gauge counted Shape/
Shape 2 clients missing an advocate/setup with ANY policy, while the
Setup Queue page itself required an ACTIVE (non-dead-status) policy.
Clients with only Cancelled/Expired/etc policies inflated the badge but
never appeared anywhere except a bare "(N skipped)" note with no names.

- setup/page.tsx: replace the bare skipped count with a full "No Active
  Policies" card listing each client (linked), policy count, what's
  missing, and a Mark N/A action
- Align the active-policy filter across setup-queue API, manager
  dashboard count, and the Prometheus setup-queue gauge so all four
  surfaces agree on what's actually actionable
2026-07-17 03:19:40 +00:00
01ecfacd04 feat(imageright): finalize two-pass audit engine and task-audit UI polish
Uncommitted work-in-progress from 2026-07-08, carried forward:
- audit-engine: refine two-pass metadata + content-inspection audit model
- audit-matching, content-inspector, shape-audit-spec: supporting matching
  and spec updates for the two-pass model
- task-audit route/panel: UI and API polish
- add @napi-rs/canvas dependency, Dockerfile/next.config adjustments for it
- test updates and additions (audit-engine, audit-decision-logic,
  run-task-audit)
- add loose dev notes (clone runbook, issues implementation, overdue filter
  bug report, shared count helper plan)
2026-07-16 22:52:41 +00:00
6dd7e3e836 fix(tasks): timezone consistency, task provenance, setup N/A, and task-generation fixes
Timezone (all users EST):
- lib/utils: hardcode APP_TIME_ZONE (America/New_York) in formatDate/
  formatRenewalDate, add formatDateTime and todayInAppTimeZone helpers
- Replace every ad-hoc toLocaleDateString/toLocaleString call across the app
  (task notes, audit log, backups, shape import, renewal groups, client
  detail) with the shared EST-aware helpers
- Fix UTC "today" bug in date-input defaults/min/max (completion date,
  reminder date) that rolled to the next calendar day after ~7-8pm ET

Task provenance:
- Task card info icon (now visible to all users, not just privileged) shows
  full origin: template, level, renewal anchor, due-date math, and who/what
  generated the task
- Include template.daysOffset and creator in task queries

Setup N/A:
- New setupNaAt/setupNaReason fields on Client; mark/restore UI and API to
  exclude non-Shape/lost-business clients from the setup queue everywhere
  it's counted (queue page, API, manager dashboard, metrics gauge)

Task generation fixes:
- auto-generate: client-level branch now gated on the renewal anchor's
  (group/policy) createdAt instead of the client's, so pre-go-live clients
  with new post-go-live groups are no longer skipped forever
- New auto-assign-tasks sweep run after every sync to assign advocates to
  tasks created by paths that don't assign directly (e.g. setup wizard)
2026-07-16 22:32:04 +00:00
30fe43fbf6 feat(imageright): two-pass metadata + content-inspection audit model
Replace the single-pass, exact-match-only audit with the two-pass model from
imageright_claim_review_audit_methodology.md, applied across all 10 SHAPE
checklist items:

- TaskAudit.status (3-state) -> TaskAuditClassification (7-state): PASS,
  PASS_WITH_NAMING_EXCEPTION, MANUAL_REVIEW, FAIL_MISSING, FAIL_LATE,
  FAIL_WRONG_ARTIFACT, NOT_APPLICABLE. New columns for confidence score,
  evidence bucket, naming-exception/manual-review flags, msg subject/sent
  date, attachment filenames, a human-readable evidence summary, and the
  full scoring signal trail (matched_signals).
- New audit-scoring.ts: weighted metadata + content scoring per the
  methodology's table, generalized to use each spec item's own
  keywords/docTypes rather than a hardcoded claim-specific list.
- New content-inspector.ts: downloads and parses `.msg` (subject, sender,
  sent date, body, attachments via @kenjiuno/msgreader), `.xlsx` (sheet
  names/cell text via xlsx), and `.pdf` (text-layer only via pdf-parse,
  no OCR) — recursing one level into email attachments.
- ImageRightClient: new getPageImageContent() using the v2 REST API
  (`/api/v2/pages/{pageId}/images/{imageId}/{version}`) — the only endpoint
  that returns raw file bytes; v1 only exposes JSON metadata. Verified live
  against a real .msg (correct OLE2 signature, exact byte-size match).
- audit-matching.ts: matchesKeywords is now plural/singular-tolerant
  (normalizeForMatch) — fixes false negatives like "Open Claims Review" not
  matching keyword "CLAIM REVIEW". Added docTypesToExtensions, mapping the
  spec's generic doc_types labels to real file extensions (evidence shows
  these labels describe file format, not ImageRight's document-type
  taxonomy).
- audit-engine.ts: auditSpecItem() replaces findBestMatch() — scores every
  in-window candidate, falls back to strict exact-match (fast path, no
  content download) when possible, otherwise deep-inspects the top
  candidate and only confirms PASS_WITH_NAMING_EXCEPTION when content
  positively confirms (not merely "score didn't decrease"). Also fixes a
  real accuracy bug: unscoped whole-file document search silently truncates
  at ~1000 docs on high-volume accounts (verified live) — ALL_TIME spec
  items now iterate every folder instead (findDocumentsSafe).
- UI/API updated for the new classification taxonomy and evidence fields.

Verified end-to-end live against the methodology doc's own worked example
(American Marine Express, Inc., IR document 12884779): real API calls, real
.msg download/parse (found both a signature image and the actual Excel
attachment), correctly classified PASS_WITH_NAMING_EXCEPTION.

68 new/updated tests covering scoring, content parsing (real xlsx bytes;
mocked msgreader/pdf-parse), fuzzy keyword matching, and all 6+1
classification outcomes via auditSpecItem with a fake ImageRight client.

Known follow-up (not resolved here): this client's stored Client.renewalDate
(2026-10-07) and PolicyGroup renewal date (2027-03-02) don't match the
2026-04-04 renewal date used in the methodology doc's own example — worth
reconciling separately, since it determines which target-date windows the
live app actually computes for this client.
2026-07-08 14:36:23 +00:00
fad9e18662 feat(imageright): Task Audit feature for SHAPE clients
- Add TaskAudit/TaskAuditStatus Prisma models linked to Client/Task/User.
- Add ImageRightClient (auth, findFilesByFileNumber, findDocuments,
  getSortedFolders) per Vertafore REST v1 API.
- Add audit engine that resolves per-item target dates/windows from the
  SHAPE_IR_Filing_Audit_Spec.md checklist, navigates real ImageRight folder
  structure, and links results to existing Tasks where found.
- Add GET/POST /api/clients/[id]/task-audit (SHAPE/SHAPE2-gated) and a
  Document Audit tab in the client detail page.
- Add Client.amsCustomerNumber (AFW_Customer.CustNo) — ImageRight's
  FileNumberPart1 expects this AMS360 account number, not the amsCustomerId
  GUID. Backfilled via one-off /api/admin/backfill-ams-customer-number.
- Fix folder/document traversal against verified live ImageRight data:
  real folders are nested under a per-year "Policy Term" folder (not flat
  SUBMISSION/PRERENEWAL as in the source spec doc), and document listing
  requires POST /api/documents/find with {FileId, ParentId} — the
  previously assumed /api/containers/{id} endpoint 404s on real ids.
- Add jest coverage for client auth/find calls and folder/doc-type matching.

Known open items (need process-owner input, not resolved here):
- Real IR document types (Correspondences, Pre-Renewal Information, Loss
  Run) don't map 1:1 to the spec's generic labels (EMAIL, EXCEL DOC, PDF).
- Spec's second folder_path segment (e.g. PRERENEWAL) has no matching real
  subfolder for at least one tested client; currently ignored for folder
  navigation and only surfaced in the audit result label.
- Whether an audit item should be skipped when no open Task exists for it,
  rather than always running and reporting INCOMPLETE.
2026-07-08 10:39:12 +00:00
835267c333 feat(automation): move task auto-generate to post-sync + admin config UI
Extracts the cron-only auto-generate logic into shared modules
(lib/sync/auto-generate.ts, automation-config.ts) and adds
group-auto-assign.ts, which attaches ungrouped policies to an existing
renewal group when their renewal dates are close. Both now also run
automatically after every AMS sync (sync-engine.ts), guarded by a
Postgres advisory lock so overlapping syncs cannot double-generate.
The external /api/cron/auto-generate endpoint remains for manual/
out-of-band triggering, delegating to the same shared engine.

Adds an admin settings UI + /api/admin/automation-settings route to
configure grace periods and toggles without a redeploy, and surfaces
the new audit actions (AUTO_GENERATE_TASKS_CLIENT, AUTO_ASSIGN_POLICY_GROUP)
in the audit log filters.

Includes a fixed AUTOMATION_GO_LIVE_AT floor (2026-07-07) in
automation-config.ts, applied to every candidate query in
auto-generate.ts and group-auto-assign.ts. Without it, the first run
after enabling this treated every historical policy/client/group that
happened to be old enough as newly eligible, generating tasks anchored
to old renewal/expiration dates in one burst (incident: 6,552 tasks
created 2026-07-07 02:01, most already 1-2 years overdue for Jeanne
Strong and Luke Billman; cleaned up same day after a verified backup).
The floor ensures automation only ever processes records created from
its go-live date forward.
2026-07-07 18:26:12 +00:00
db37313631 fix(tasks): allow self-referencing userId filter for non-privileged users
Advocates could not filter their own task list by client because the
/api/tasks endpoint treated any userId query param as a request to
view another user's tasks, rejecting non-Admin/Manager callers with
403 even when userId matched their own session id.
2026-07-07 00:48:00 +00:00
b1b0dfa64d Fix: align task visibility filters across all API routes and dashboards
- api/tasks/route.ts: fix group-expiry filter to never hide open tasks;
  replace dueDate-based age filter with completedAt-based filter so open
  tasks are always visible regardless of how old they are
- api/dashboard/workload/route.ts: add dead-policy exclusion to base
  task filter so overdue counts and per-user workload rows exclude tasks
  on cancelled/expired/non-renewed policies
- manager/page.tsx: same dead-policy exclusion on teamMembers task query
- api/metrics/route.ts: fix horizon_tasks_overdue to exclude dead-policy tasks
2026-06-02 00:01:01 +00:00
20f7ec1188 Fix: 8 issues from Horizon Issues & Next Steps doc
1. Tasks disappearing (Mimi bug) - open tasks now always visible
   regardless of renewal group date; only terminal tasks filter by group age

2. Star date change recalculates task due dates - PATCH policy-group
   now updates dueDate on all open template tasks when renewalDate changes

3. Auto task generation on setup complete - wizard calls generate-tasks
   for each saved group immediately after Save & Complete

4. Manual sync date range - defaults are now dynamic (prev year to +2y)
   instead of hardcoded 2026-01-01 / 2026-12-31

5. Setup queue filters out clients with no active policies; shows
   skipped count so managers know what was excluded

6. Audit logging gap fixed - notes route now emits TASK_STATUS_CHANGED
   with old+new status when note submission also changes status

7. Renewal day-count warnings now shown on individual policy cards
   in client detail (<=30d destructive, <=90d secondary badge)

8. Client notes now show save timestamp after editing
2026-05-28 23:33:54 +00:00
133dd13c29 Fix: show completed tasks based on completedAt not dueDate
Terminal tasks (COMPLETED/CANCELLED/NA) were gated on dueDate >= cutoff,
so bulk-closed tasks with old due dates never appeared in task lists even
though they were just completed. Switch the 7-day recency check to use
completedAt instead — a task completed this week always shows regardless
of when it was due.
2026-05-20 17:38:51 +00:00
79b6991b31 Add: /api/admin/bulk-close-pre-cutoff route with audit logging
Marks all open tasks with dueDate < 2026-04-01 as COMPLETED.
Supports ?dryRun=true for safe preview before execution.
Writes batched AuditLog entries + a summary entry per run.
Admin-only (403 for non-admins).
2026-05-20 17:27:27 +00:00
c20d6b8f1a Fix: align overdue task counts across all surfaces
Manager page and workload API were bounding overdue by a configurable
window (e.g. last 30 days), while the tasks page counted ANY open task
past due with no lower bound. This caused Mimi/Dawn's numbers to diverge.

All three surfaces now use the same definition: open task + dueDate < today.
2026-05-20 17:10:09 +00:00
970ffe2864 Feature: task origin/business logic visibility for managers & admins
- Task cards show an info (ⓘ) icon in the Level row for privileged users
  Tooltip: e.g. '90 days before renewal · Group level · Template: Request Loss Runs'
- Edit modal shows a read-only Task Origin callout at top for privileged users
- Added template include to all task queries (tasks page, client page, client tasks API)
- Also applied the open-task cutoff fix to /api/clients/[id]/tasks/route.ts (same bug as Luke's)
2026-05-19 03:49:39 +00:00
a4dfa0db59 Fix: open overdue tasks no longer hidden by 7-day age cutoff
RCA: the dueDate >= cutoff filter was incorrectly excluding open tasks
more than 7 days overdue. The cutoff now only applies to terminal tasks
(COMPLETED/CANCELLED/NA) to suppress ancient clutter. Open tasks of any
age are always returned.

Fixes tasks/page.tsx and clients/[id]/page.tsx.
2026-05-19 03:24:14 +00:00
e6485b35dc Fix setup wizard starred group persistence + pencil edit
- SetupWizard: honor client.renewalDate when determining which group is starred on reopen
- PolicyGroupManager: defensively handle Date or string in handleOpenEdit to unblock pencil
2026-04-24 20:57:48 +00:00
b44bddfc6a Follow-up fixes: starred group, edit pencil, sync warning, service type
- Starred group: PolicyGroupManager now uses client.renewalDate to identify anchor, not earliest date
- Setup API: recalculates client-level task due dates when starred group changes
- Client tasks API: uses client.renewalDate to pick anchor group, fallback to earliest
- PolicyGroupManager: fixed IIFE double-close that broke pencil/edit button
- Template sync: returns levelWarning when level changed; UI shows toast.warning
- Additional Services: added Service Type toggle (Service / Reminder); stored as taskGroup
- TaskCard: shows Service/Reminder badge on ad-hoc tasks
2026-04-24 19:56:44 +00:00
8b43a25f4d Task system improvements batch
- Fix due date off-by-one: parse date-only strings as local time in formatDate/formatRenewalDate
- Additional Services: dynamic fetch of policies/groups when no context provided
- Template sync: admin button + POST /api/templates/[id]/sync endpoint
- Policy<>Group movement: confirmation dialog, cancel-policy-tasks, generate-policy-tasks APIs
- Client-level tasks: show anchor group renewal date with star in TaskCard
- Policy group manager: show star on anchor (earliest renewal) group
2026-04-24 18:26:43 +00:00
9331618ba6 Task templates: add policyTypeFilter field to form, table, and API 2026-04-23 12:40:19 +00:00
47fb5317a9 Admin backups UI: list, run-now, download, delete + backup volume mounted to app 2026-04-23 12:31:24 +00:00
f3a9fb6670 Clean restart: policyTypeFilter on templates, wipe+regenerate Apr 1+ endpoint, admin UI button 2026-04-23 11:06:39 +00:00
a4bc1bfe4f Login: remove white card, blend form into gold background 2026-04-14 12:46:51 +00:00
ca868f5226 Login page: right panel Seubert gold #D6A620, white card for form 2026-04-14 12:12:50 +00:00
792f1c81c2 Fix: include carrierName, writingCompanyName, policyGroup in SSR task data 2026-04-14 02:34:03 +00:00
07945ec1d9 Consistent task cards: client detail now uses shared TaskCard
- Extract TaskCard into components/tasks/task-card.tsx (full-featured)
- Client tasks API now includes policy, policyGroup, taskNotes
- client-detail replaces inline render with shared TaskCard
- Features now consistent: status dropdown, complete/NA/edit actions,
  inline notes panel, carrier info, policy group popover, due date
  urgency colors, priority dot
2026-04-14 02:13:34 +00:00
b3da81a5d8 Fix Has Policies filter to exclude dead-status policies
policies: some: {} was matching Non-Renewed, Cancelled, etc.
Now excludes Cancelled/Expired/Non-Renewed/Rewritten/Not taken
2026-04-14 01:58:06 +00:00
db9dae7c7c Scope dashboard KPIs to Shape clients only
- Client count: Shape/Shape2 designation only
- Policy count: active Shape policies (excludes dead statuses)
- Task count: open tasks on Shape clients (excludes NA/CANCELLED)
- Completion rate: excludes NA/CANCELLED from denominator
- /api/metrics intentionally left as system-wide (Prometheus)
2026-04-14 00:36:17 +00:00
c07e02855e Fix overdue counts on manager page
- teamMembers query now scoped to Shape clients + active tasks only
- TeamMembersByDepartment overdue calc uses overdueWindowDays window (default 7d)
- Workload API per-user fetch now only loads active tasks (massive perf win)
- Remove Completed/Completion% columns from workload table (no longer meaningful)
- overdueWindowDays passed through page -> client -> component chain
2026-04-14 00:27:47 +00:00
191698088b Manager overdue window: configurable via Admin > Settings
- Default 7 days: overdue tasks shown only within last N days
- New /api/admin/manager-settings endpoint (GET/PUT, AppSetting key)
- Workload API reads setting and applies to both summary count and per-user table
- Overdue card now shows 'past due within Nd' context label
- Admin > System Settings: new Manager Dashboard card with day input
2026-04-14 00:17:31 +00:00
27247f77f0 Fix Additional Service modal: department enum mapping and timing value
- Map display labels to DepartmentType enum values (CLAIMS, PERSONAL_LINES, etc.)
- Fix timing from invalid 'ONGOING' to 'PRE_RENEWAL' (only valid values)
- Remove unused TIMINGS constant
2026-04-13 22:55:59 +00:00
5934ff7c4f Fix Manager tab KPIs and workload metrics
- setupQueueCount: add policies: { some: {} } filter (match setup-queue API)
- recentTasks: scope to Shape clients, order by updatedAt not createdAt
- Workload API: scope all metrics to Shape clients only
- Workload API: filter tasks by task.department not assignee department
- Workload API: exclude NA/CANCELLED from totalTasks and completion rate denominator
- Workload API: scope userAssignments filter to match department/client scope
2026-04-13 22:44:50 +00:00
c40dd68360 Fix Shape import resolvePolicyLink: use nearest match, no date window
- Removed ±40 day window restriction that caused prior-cycle tasks to miss their group/policy
- Now finds nearest group/policy by absolute date proximity for any cycle
- Deleted 310 client-level orphans created by previous import runs
2026-04-13 20:39:09 +00:00
4e54b7e38c Fix: POLICY-level tasks now generated for all active policies (grouped or not)
- Historical reset: removed policyGroupId: null filter from policy loop, use level POLICY only
- Gap fill: same fix - all active future policies get POLICY-level tasks
- BOTH-level templates remain on groups (for grouped) or policies (for ungrouped)
- ~3500 grouped policies were missing their POLICY tasks (loss runs, mod factor, etc)
2026-04-13 20:25:10 +00:00
02afceb0c5 Fix Shape import: resolve policyId/policyGroupId when creating new tasks
- Add resolvePolicyLink() to find closest policy group or policy by effectiveDate window
- Include template level in DbTemplate interface and loadDbState query
- New tasks created by import now carry correct policyId or policyGroupId
- Delete all 492 orphaned POLICY/RENEWAL_GROUP tasks (no policy link)
2026-04-13 19:55:40 +00:00
00b5fab1ba Add Gap Fill: delete 507 orphaned tasks, new /api/admin/gap-fill endpoint, button in shape-import panel
- Deletes tasks where POLICY/RENEWAL_GROUP template has no policy_id/policy_group_id
- Gap Fill creates missing tasks per group/policy/client without overwriting existing ones
- Existence check within 5-day window prevents duplicates
- Gap Fill button added to shape-import admin panel with inline result summary
2026-04-13 19:40:34 +00:00
36076ce90d Add carrierName/writingCompanyName to tasks GET and PATCH API responses 2026-04-13 18:20:07 +00:00
e712420347 Min-2 policy rule for groups (singles \u2192 unassigned); fix setup-queue badge 0-policy filter 2026-04-13 17:57:06 +00:00
a6fa5d12ea Task card carrier/writing co + group popover; fix Renews date; filter 0-policy setup queue; login tagline; advocate reassign dialog 2026-04-13 17:42:36 +00:00
384821de33 Fix: exclude static image files from auth middleware matcher 2026-04-13 02:58:02 +00:00
cf79b3453d Signin: use black logo with CSS invert for white rendering on green panel 2026-04-13 02:52:33 +00:00
5406d24c1f Signin: use plain img tags for logos to fix rendering, white logo on green panel 2026-04-13 02:45:58 +00:00
e0116b0faf Signin: color logo on left, road-green icon on right, black road favicon 2026-04-13 02:29:46 +00:00
e588b98127 Signin: use color Seubert logo on white right panel 2026-04-13 02:21:26 +00:00