Commit Graph

282 Commits

Author SHA1 Message Date
Chandler Copeland
136eaf0723 docs(13-03): complete AI Auto-place UI wire-up plan — violet button, aiPlacementKey, handleAiAutoPlace
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 17:10:01 -06:00
Chandler Copeland
bfdaee14ed feat(13-03): add AI Auto-place button to PreparePanel and wire DocumentPageClient handler
- Add onAiAutoPlace prop and handleAiAutoPlaceClick with aiLoading state to PreparePanel
- Add violet AI Auto-place button above Preview button (Draft documents only)
- Add aiPlacementKey state and handleAiAutoPlace callback in DocumentPageClient
- handleAiAutoPlace: POST /api/documents/[id]/ai-prepare, merges textFillData, increments aiPlacementKey, resets previewToken
- Pass aiPlacementKey to PdfViewerWrapper and onAiAutoPlace to PreparePanel
2026-03-21 17:08:10 -06:00
Chandler Copeland
3e11eef1c4 feat(13-03): add aiPlacementKey prop to FieldPlacer and thread through PdfViewerWrapper/PdfViewer
- Add aiPlacementKey?: number to FieldPlacerProps interface
- Add aiPlacementKey to loadFields useEffect dependency array for re-fetch on AI placement
- Thread aiPlacementKey through PdfViewer and PdfViewerWrapper prop chains
2026-03-21 17:07:01 -06:00
Chandler Copeland
970bb4f7cf docs(13-02): complete ai-prepare route plan — POST handler, guard chain, AI pipeline
- 13-02-SUMMARY.md created with accomplishments, decisions, file list
- STATE.md: plan position advanced to 2/4, decisions logged, session updated
- ROADMAP.md: phase 13 progress updated to 2 summaries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 17:05:37 -06:00
Chandler Copeland
e91f29e555 feat(13-02): implement POST /api/documents/[id]/ai-prepare route
- Auth guard (401), OPENAI_API_KEY guard (503), not-found (404)
- Draft-only guard (403), path traversal guard (403)
- Loads document with client relation via Drizzle with: { client: true }
- Calls extractPdfText then classifyFieldsWithAI in try/catch (500 on error)
- Writes SignatureFieldData[] to DB signatureFields; status stays Draft
- Returns { fields, textFillData } keyed by field UUID
2026-03-21 17:04:00 -06:00
Chandler Copeland
24e1f5aa00 docs(13-01): complete AI foundation layer plan — extract-text, field-placement, unit tests
- Create 13-01-SUMMARY.md with TDD execution results and decisions
- Update STATE.md: phase 13 in progress, plan 1/4 complete
- Update ROADMAP.md: phase 13 status set to In Progress (1/4 summaries)
- Mark AI-01, AI-02 requirements complete in REQUIREMENTS.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 17:02:25 -06:00
Chandler Copeland
c1e1e5ec49 feat(13-01): implement aiCoordsToPagePdfSpace and AI field utilities
- Install openai 6.32.0 (npm package, listed in dependencies)
- Create src/lib/ai/extract-text.ts — pdfjs-dist legacy build server-side text extraction
  - extractPdfText(filePath) returning PageText[] with page, text, width, height
  - GlobalWorkerOptions.workerSrc = '' for Node.js fake-worker mode
  - Text per page capped at 2000 chars for GPT-4o-mini context limit
- Create src/lib/ai/field-placement.ts — GPT-4o-mini structured output + coord conversion
  - aiCoordsToPagePdfSpace() converts AI top-left pct coords to PDF bottom-left points
  - classifyFieldsWithAI() uses manual json_schema (NOT zodResponseFormat — broken with Zod v4)
  - Standard field sizes: checkbox=24x24pt, others=144x36pt
  - textFillData keyed by field UUID (not label) per Phase 12.1 design
- All 3 unit tests pass (GREEN phase confirmed)
2026-03-21 17:00:34 -06:00
Chandler Copeland
f7d74c0523 test(13-01): add failing aiCoordsToPagePdfSpace unit tests
- Add ai-coords.test.ts with 3 test cases covering US Letter (612x792 pts)
- Tests import from lib/ai/field-placement which does not exist yet (RED phase)
- Cases: text field near top, checkbox near bottom-right, client-sig at center
2026-03-21 16:59:11 -06:00
Chandler Copeland
df4676c23c docs(13): create phase 13 AI field placement plan
4 plans in 4 sequential waves covering:
- Plan 01 (TDD): openai install, extract-text.ts, field-placement.ts, aiCoordsToPagePdfSpace unit test
- Plan 02: POST /api/documents/[id]/ai-prepare route with all guards
- Plan 03: UI wiring — aiPlacementKey in FieldPlacer, AI Auto-place button in PreparePanel
- Plan 04: Unit test gate + human E2E verification checkpoint

Satisfies AI-01, AI-02. Completes v1.1 Smart Document Preparation milestone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 16:54:43 -06:00
Chandler Copeland
c317eb2f53 docs(13): research AI field placement and pre-fill phase 2026-03-21 16:47:28 -06:00
Chandler Copeland
2f30503a56 docs(phase-12.1): complete phase execution 2026-03-21 16:36:47 -06:00
Chandler Copeland
698b414249 docs(12.1-02): complete per-field text editing and quick-fill plan — human verification approved
- Task 3 (human-verify checkpoint) approved: all 12 verification steps passed
- Updated SUMMARY.md: tasks_completed 3, requirements-completed TXTF-01/02/03, verification section
- STATE.md: Phase 12.1 marked complete; session stopped-at updated; decision recorded
- ROADMAP.md: 12.1-01 and 12.1-02 plans marked complete ([x]); roadmap update-plan-progress confirmed 2/2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 16:32:30 -06:00
Chandler Copeland
dbca290dbb docs(12.1-02): complete state bridge plan; awaiting human-verify checkpoint
- Create 12.1-02-SUMMARY.md: selectedFieldId + textFillData state lifting; QuickFillPanel replacing TextFillForm
- Update STATE.md: position at checkpoint Task 3 (human verification); 3 new decisions logged
- Update ROADMAP.md: phase 12.1 progress (2/2 SUMMARYs)
- Mark TXTF-02 complete in REQUIREMENTS.md
2026-03-21 16:27:35 -06:00
Chandler Copeland
d2ebb2cc67 feat(12.1-02): replace TextFillForm with QuickFillPanel in PreparePanel; delete TextFillForm.tsx
- Add textFillData, selectedFieldId, onQuickFill props to PreparePanelProps
- Remove textFillData local state and handleTextFillChange (parent now owns state)
- Remove TextFillForm import and JSX block
- Add QuickFillPanel: shows Client Name, Property Address, Client Email quick-fill buttons when selectedFieldId is non-null; idle state message when no field selected
- handlePreview and handlePrepare use textFillData from props
- Delete TextFillForm.tsx (label-keyed generic form no longer used)
2026-03-21 16:25:57 -06:00
Chandler Copeland
f395819acd feat(12.1-02): extend DocumentPageClient with selectedFieldId + textFillData shared state
- Add selectedFieldId and textFillData state variables
- Add handleFieldValueChange and handleQuickFill callbacks (both call setPreviewToken(null))
- Pass selectedFieldId, textFillData, onFieldSelect, onFieldValueChange to PdfViewerWrapper
- Pass textFillData, selectedFieldId, onQuickFill to PreparePanel
- textFillData starts as {} (no clientPropertyAddress seeding)
2026-03-21 16:25:51 -06:00
Chandler Copeland
46c7aaa7d5 docs(12.1-01): complete per-field text fill and click-to-select plan
- SUMMARY.md: document field-ID-keyed text fill and click-to-select interaction
- STATE.md: advance to Phase 12.1 Plan 1 complete; add 3 key decisions
- ROADMAP.md: update phase 12.1 progress (1/2 plans complete)
- REQUIREMENTS.md: mark TXTF-01 and TXTF-03 complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 16:23:42 -06:00
Chandler Copeland
eaf377d97d feat(12.1-01): add optional text-edit props and click-to-select interaction
- PdfViewerWrapper: add selectedFieldId?, textFillData?, onFieldSelect?, onFieldValueChange? and forward to PdfViewer
- PdfViewer: add same 4 optional props, forward to FieldPlacer; call onFieldSelect?.(null) on page navigation
- FieldPlacer: extend FieldPlacerProps with 4 new optional props
- DroppableZone: add optional onClick prop for background deselect
- renderFields: text fields show inline input when selected (isSelected), value/label otherwise
- Per-field onClick: text fields call onFieldSelect(id), non-text fields call onFieldSelect(null)
- Cursor updated to 'text' for text field type; boxShadow ring on selected state
2026-03-21 16:22:02 -06:00
Chandler Copeland
df02a1e3f7 feat(12.1-01): replace positional text fill with field-ID-keyed lookup
- Remove AcroForm Strategy A (getForm/flatten) — no longer needed
- Remove positional sorting loop (textFields_sorted, remainingEntries, fieldConsumedKeys)
- Remove Strategy B top-of-page UUID stamp (unstampedEntries)
- Add Phase 12.1 field-ID-keyed loop: textFields[field.id] direct lookup
- Update JSDoc to document new keying strategy
2026-03-21 16:20:25 -06:00
Chandler Copeland
62ba448460 docs(12.1): create phase plan — per-field text editing and quick-fill 2026-03-21 16:15:55 -06:00
Chandler Copeland
0eeed0fb73 docs(12.1): research phase per-field text editing and quick-fill
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 16:07:45 -06:00
Chandler Copeland
974574e561 docs(phase-12.1): add per-field text editing gap phase to roadmap and requirements 2026-03-21 16:03:37 -06:00
Chandler Copeland
db8a63f6a3 docs(phase-12): complete phase execution 2026-03-21 16:01:59 -06:00
Chandler Copeland
513bbe96d8 docs(12-02): complete filled-document-preview plan 02 — PREV-01 human-verified
- Update 12-02-SUMMARY.md: add bug fix commits (43f396b scroll lock+portal, bce2a98 text fill coords), human approval, known gap (Phase 12.1 text fill UX redesign deferred)
- STATE.md: Phase 12 COMPLETE, progress 100% (13/13), add decisions for portal modal, text fill coords, Phase 12.1 gap; update session Stopped At
- ROADMAP.md: Phase 12 marked Complete (2/2 summaries)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 15:58:01 -06:00
Chandler Copeland
bce2a980d2 fix(12-02): draw text fill values at placed text field box coordinates
- Bug 3: text type fields previously drew nothing at field coordinates;
  textFillData values were only stamped at top of page 1 via Strategy B,
  making them invisible to the agent inspecting the placed boxes
- Sort placed text fields by page asc / y desc (reading order) and assign
  textFillData entries sequentially to each field box position
- Text drawn at field.x+4, field.y+4 with font size capped 6–11pt to fit
  within the field height; dark near-black color for legibility
- fieldConsumedKeys set tracks which entries were rendered at field coords;
  Strategy B only stamps remaining entries not consumed by a field box
- TypeScript compiles clean; zero errors
2026-03-21 15:50:30 -06:00
Chandler Copeland
43f396b4c5 fix(12-02): body scroll lock and z-index/portal fix for PreviewModal
- Bug 1: add useEffect that locks document.body.overflow on mount and
  restores original value on unmount — prevents page scrolling behind modal
- Bug 2: render modal via ReactDOM.createPortal to document.body so it
  escapes the sticky sidebar's stacking context; raise z-index to 9999
  so backdrop sits definitively above all FieldPlacer overlay boxes
  (zIndex: 10/12) and dnd-kit DragOverlay regardless of parent context
2026-03-21 15:50:22 -06:00
Chandler Copeland
422c9a89aa docs(12-02): checkpoint after tasks 1+2 — PreparePanel preview wiring complete
- SUMMARY.md created documenting Tasks 1+2 completion
- STATE.md updated: position at checkpoint:human-verify Task 3
- Decisions recorded: previewToken lifted to DocumentPageClient, wiring pattern
2026-03-21 15:38:18 -06:00
Chandler Copeland
720d07fd54 feat(12-02): FieldPlacer onFieldsChanged callback prop after every persistFields call
- Add onFieldsChanged?: () => void to FieldPlacerProps interface
- Destructure onFieldsChanged in function signature
- Call onFieldsChanged?.() after persistFields in handleDragEnd (new field drop)
- Call onFieldsChanged?.() after persistFields in handleZonePointerUp move case
- Call onFieldsChanged?.() after persistFields in handleZonePointerUp resize case
- Call onFieldsChanged?.() after persistFields in delete button onClick
- Add onFieldsChanged to useCallback dependency arrays (handleDragEnd, handleZonePointerUp)
2026-03-21 15:36:56 -06:00
Chandler Copeland
de195a3e80 feat(12-02): PreparePanel preview state, button, gating, modal, and DocumentPageClient wiring
- Add previewToken/onPreviewTokenChange props to PreparePanel (lifted to DocumentPageClient)
- Add handlePreview async function fetching POST /api/documents/[id]/preview
- Add Preview button (gray-700) before Send button; text cycles Preview/Preview again
- Gate Send button on previewToken === null (requires fresh preview before send)
- Wrap TextFillForm onChange to reset previewToken on text fill changes
- Render PreviewModal conditionally when showPreview && previewBytes
- Create DocumentPageClient.tsx: holds previewToken state, passes reset callback to both FieldPlacer (via PdfViewerWrapper/PdfViewer) and PreparePanel
- Update PdfViewerWrapper and PdfViewer to accept and forward onFieldsChanged prop
- Update page.tsx to use DocumentPageClient instead of direct PreparePanel/PdfViewerWrapper siblings
2026-03-21 15:36:47 -06:00
Chandler Copeland
aba622a765 docs(12-01): complete filled-document-preview plan 01
- SUMMARY.md with task commits, decisions, self-check
- STATE.md updated: position advanced to phase 12 plan 1/2 complete
- ROADMAP.md updated: phase 12 in progress (1/2 plans complete)
- PREV-01 marked complete in REQUIREMENTS.md
2026-03-21 15:31:42 -06:00
Chandler Copeland
f4589391ff feat(12-01): PreviewModal component with react-pdf Document/Page
- 'use client' component accepting ArrayBuffer prop and onClose callback
- Configures pdfjs worker independently from PdfViewer module
- Imports AnnotationLayer.css and TextLayer.css
- Prev/Next page navigation with disabled states
- Fixed overlay (rgba black 70%) with white inner container
2026-03-21 15:30:07 -06:00
Chandler Copeland
99205bca9f feat(12-01): POST /api/documents/[id]/preview route
- Auth-guarded Next.js 15 route handler with async params
- Versioned temp path (_preview_{timestamp}.pdf) — never overwrites _prepared.pdf
- Path traversal guard mirrors prepare route
- Mirrors 422 guards for agent-signature-missing and agent-initials-missing
- try/finally ensures temp file deleted after bytes are read
2026-03-21 15:29:47 -06:00
Chandler Copeland
10d4eb738a docs(12-filled-document-preview): create phase 12 plan
Two-plan wave structure for PREV-01: preview API route + modal (Plan 01,
Wave 1) then PreparePanel/FieldPlacer wiring + human verification (Plan 02,
Wave 2). Send button gated on previewToken staleness detection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 15:25:48 -06:00
Chandler Copeland
06b96cd3c2 docs(12): research phase filled-document-preview 2026-03-21 15:20:26 -06:00
Chandler Copeland
f3cf24078b docs(phase-11.1): complete phase execution 2026-03-21 15:15:08 -06:00
Chandler Copeland
a9607763fa docs(11.1-03): complete agent-and-client-initials E2E verification plan 2026-03-21 15:08:49 -06:00
Chandler Copeland
babc92be34 docs(11.1-02): complete agent-initials prepare pipeline plan
- Add 11.1-02-SUMMARY.md with plan execution results
- Update STATE.md: current position, session continuity, decisions
- Update ROADMAP.md: phase 11.1 progress (2/3 summaries)
2026-03-21 15:05:00 -06:00
Chandler Copeland
c876579637 feat(11.1-02): update prepare route to fetch agentInitialsData, add 422 guard, pass to preparePdf
- Fetch agentInitialsData alongside agentSignatureData in single DB query
- Add 422 guard returning { error: 'agent-initials-missing' } when agent-initials fields present but no initials saved
- Pass agentInitialsData as 6th arg to preparePdf()
2026-03-21 15:03:14 -06:00
Chandler Copeland
fae1cf1b68 feat(11.1-02): add agentInitialsData param to preparePdf and embed at agent-initials fields
- Add agentInitialsData as 6th optional param (default null)
- Embed agent initials PNG once before field loop (embed-once-draw-many pattern)
- Add agent-initials branch in field loop: drawImage at field coordinates
- Existing initials (client-initials) and agent-signature branches untouched
2026-03-21 15:02:51 -06:00
Chandler Copeland
ec7f726cae docs(11.1-01): complete agent initials storage and UI plan
- Create 11.1-01-SUMMARY.md with task commits, decisions, and file inventory
- Update STATE.md: position, decisions (4 recorded), session continuity
- Update ROADMAP.md: phase 11.1 progress (1/3 plans complete, In Progress)
- Mark INIT-01, INIT-02, INIT-03, INIT-04 complete in REQUIREMENTS.md
2026-03-21 15:01:32 -06:00
Chandler Copeland
d9f618f69a feat(11.1-01): AgentInitialsPanel component, profile page section, FieldPlacer token
- Create AgentInitialsPanel.tsx (clone of AgentSignaturePanel with 80px canvas, /api/agent/initials endpoint)
- Update profile/page.tsx to fetch agentInitialsData and render AgentInitialsPanel below signature section
- Add orange 'Agent Initials' token (7th entry) to FieldPlacer PALETTE_TOKENS
- Add 'agent-initials' to FieldPlacer validTypes Set
2026-03-21 14:59:29 -06:00
Chandler Copeland
33f499c61b feat(11.1-01): DB migration, API routes, schema type updates for agent initials storage
- Add agentInitialsData text column to users table (drizzle/0009_luxuriant_catseye.sql)
- Add 'agent-initials' to SignatureFieldType union in schema.ts
- Update isClientVisibleField() to exclude both agent-signature and agent-initials
- Create GET/PUT /api/agent/initials route with auth guard and 50KB size limit
2026-03-21 14:58:39 -06:00
Chandler Copeland
ae17e017d3 docs(11.1): create phase plan — agent and client initials
Added INIT-01 through INIT-04 requirements to REQUIREMENTS.md. Updated
ROADMAP.md with Phase 11.1 goal, success criteria, and plan list. Created
three plan files mirroring Phase 11 structure: 11.1-01 (DB migration, API
routes, AgentInitialsPanel, FieldPlacer token), 11.1-02 (preparePdf
agentInitialsData param + prepare route guard), 11.1-03 (human E2E
verification checkpoint).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:55:00 -06:00
Chandler Copeland
e673799246 docs(11.1): research phase — agent and client initials
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:46:00 -06:00
Chandler Copeland
efa7edddbb docs(phase-11): complete phase execution 2026-03-21 14:39:13 -06:00
Chandler Copeland
e594e27f4e docs(11-03): complete Phase 11 human verification — all AGENT requirements confirmed
- Created 11-03-SUMMARY.md: E2E human verification approved; AGENT-01 through AGENT-04 confirmed live
- Updated STATE.md: Phase 11 complete (11/13 phases), plan 3/3 done, decisions appended
- Updated ROADMAP.md: Phase 11 marked 3/3 Complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:33:10 -06:00
Chandler Copeland
f8de782a64 docs(11-02): complete agent signature bake-in prepare pipeline plan
- 11-02-SUMMARY.md: preparePdf() embeds agent PNG + prepare route 422 guard
- STATE.md: advance to plan 2 of 3, add phase 11-02 decisions, update metrics
- ROADMAP.md: phase 11 progress updated (2/3 plans complete)
- REQUIREMENTS.md: AGENT-04 marked complete
2026-03-21 14:08:37 -06:00
Chandler Copeland
b2e9810d60 feat(11-02): prepare route fetches agentSignatureData, 422 guard, passes to preparePdf
- Import users and getFieldType from @/lib/db/schema
- Strengthen session guard to !session?.user?.id (matches established pattern)
- Fetch agentSignatureData from users table for the authenticated agent
- 422 guard: return { error: 'agent-signature-missing' } when agent-sig fields exist but no signature saved
- Pass agentSignatureData as 5th arg to preparePdf()
2026-03-21 14:07:01 -06:00
Chandler Copeland
d9652e1f87 feat(11-02): preparePdf() gains agentSignatureData param and embeds at agent-sig fields
- Add optional agentSignatureData: string | null = null as 5th parameter
- Import PDFImage from @cantoo/pdf-lib for typed agentSigImage variable
- Embed PNG once before field loop, store as agentSigImage
- Replace agent-signature stub with drawImage at field.x/y/width/height
2026-03-21 14:06:12 -06:00
Chandler Copeland
f1dbf45e37 docs(11-01): complete agent saved signature storage and UI plan
- Create 11-01-SUMMARY.md documenting agentSignatureData DB column, API routes, AgentSignaturePanel, profile page, nav link, FieldPlacer token
- Update STATE.md: advance to Plan 1 of 3, record Phase 11 decisions and metrics
- Update ROADMAP.md: Phase 11 now In Progress (1/3 summaries)
- Mark requirements AGENT-01, AGENT-02, AGENT-03 complete in REQUIREMENTS.md
2026-03-21 14:04:54 -06:00
Chandler Copeland
f383f91445 feat(11-01): AgentSignaturePanel, profile page, PortalNav link, FieldPlacer token
- Create AgentSignaturePanel.tsx with signature_pad canvas, save/update/thumbnail flow
- Create /portal/profile page (server component fetching agentSignatureData)
- Add Profile link to PortalNav navLinks array
- Add red 'Agent Signature' token to FieldPlacer PALETTE_TOKENS (6th entry)
2026-03-21 14:02:51 -06:00