Commit Graph

21 Commits

Author SHA1 Message Date
paulh 8510eacecb fix(ralph-loop): capture check_output status safely under set -e
When the agent emits no promise signal, check_output returns 1 (continue).
Under set -euo pipefail, a bare function call returning non-zero exits the
script before status=$? can capture it. Fix: use the || idiom so the
non-zero return is handled rather than triggering set -e.

Agent: human
Tests: N/A
Tests-Added: 0
TypeScript: N/A
2026-04-09 22:26:11 -04:00
paulh 207358fa7d feat(clm-admin): add persistEnvelopeResult() and extend CaseContext with eSignature fields
- Add 5 eSignature fields to CaseContext DTO (FR-004)
- Extend getCaseContext() SOQL to include all 5 envelope tracking fields
- Add @AuraEnabled persistEnvelopeResult() following persistDocGenResult pattern (FR-003)
  - Writes ESignature_Envelope_Id__c, ESignature_Envelope_Status__c, ESignature_Sent_At__c
  - Writes ESignature_Envelope_Url__c when non-blank; does NOT touch ESignature_Completed_At__c

Agent: claude-sonnet-4-6
Tests: 7/7 passing | CLMAdminServiceTest
Tests-Added: 0
TypeScript: N/A (Apex project)
2026-04-09 22:21:29 -04:00
paulh 6fe75d8ab3 test(esignature): add createEnvelope() test coverage — TC-001, TC-002, blank email guard
Three new test methods in DocusignESignatureServiceTest:
- createEnvelopeReturnsSuccessResultOnHttp201 (TC-001): mocks 201, asserts success=true, envelopeId, status
- createEnvelopeReturnsFailureResultOnHttp400 (TC-002): mocks 400, asserts success=false, errorMessage non-null
- createEnvelopeReturnsEarlyWhenEmailIsBlank: asserts early return with errorMessage when Appraiser_Email__c is blank

All 11 tests pass (11/11). Satisfies NFR-001 for createEnvelope().

Agent: claude-sonnet-4-6
Tests: 11/11 passing
Tests-Added: +3
TypeScript: N/A (Apex project)
2026-04-09 22:19:38 -04:00
paulh c3421e858f feat(esignature): add EnvelopeCreateResult class and createEnvelope() method
Adds EnvelopeCreateResult inner DTO and createEnvelope(Id, String, String)
to DocusignESignatureService. Option A (template-based): POSTs to
/v2.1/accounts/{accountId}/envelopes with templateId, templateRoles
(Signer), and status=sent. Guards blank templateId and blank appraiser
email; catches all exceptions and wraps in result. Named credential
sourced from CLM_Account_Setting__mdt per ADR-002.

Agent: claude-sonnet-4-6
Tests: 8/8 passing | N/A (no new test methods — Task 3 covers test coverage)
Tests-Added: 0
TypeScript: N/A (Apex project)
2026-04-09 22:17:08 -04:00
paulh e4b7456dc1 feat(esignature): add 5 eSignature tracking fields to Appraiser_Case__c
Add ESignature_Envelope_Id__c (Text 255), ESignature_Envelope_Status__c
(Text 50), ESignature_Sent_At__c (DateTime), ESignature_Completed_At__c
(DateTime), and ESignature_Envelope_Url__c (URL) to Appraiser_Case__c.
Deployed to appraiser-dev — Status: Succeeded.

Agent: claude-sonnet-4-6
Tests: N/A (metadata-only)
Tests-Added: 0
TypeScript: N/A (Apex project)
2026-04-09 22:15:07 -04:00
paulh 66be5d83ff fix(ralph-loop): replace with three-tier session reset detection from master
Supersedes the simple polling version written this session. The master
harness version (from the other machine) has:
  Tier 1 — Anthropic API probe via ANTHROPIC_API_KEY if available
  Tier 2 — Parse reset time from agent output ("resets 11am America/New_York")
  Tier 3 — Seeded --session-ends timestamp argument
  Tier 4 — Fixed fallback sleep (--retry-wait, default 1800s)

Agent: human
Tests: N/A
Tests-Added: 0
TypeScript: N/A
2026-04-09 21:56:03 -04:00
paulh 82e10ff810 fix(ralph-loop): add session limit detection and auto-recovery
When claude -p hits the Pro subscription usage limit, the old loop had
no detection — it would find no <promise> signal, treat it as a normal
continuation, and immediately retry, burning all --max iterations.

New behaviour:
- check_output() returns status 4 when the log contains any usage/rate
  limit message (case-insensitive, multiple pattern variants)
- wait_for_session_reset() polls via a trivial probe call every
  SESSION_POLL_INTERVAL seconds (default: 600s / 10 min) until claude
  responds cleanly again
- When rate-limited, the same iteration is retried (i is not incremented)
  so no task is skipped or double-counted
- set -e is temporarily suspended around agent calls so a non-zero claude
  exit doesn't kill the bash process

Also updated the master template in docs/agent-harness/ralph-loop.sh.

Agent: human
Tests: N/A
Tests-Added: 0
TypeScript: N/A
2026-04-09 21:39:29 -04:00
paulh b1c199d21d chore: scaffold agent harness for Phase 2 eSignature envelope creation
Adds the ralph loop harness artifacts to drive autonomous implementation
of Phase 2. State lives in IMPLEMENTATION_PLAN.md so work survives
session resets — restart ralph-loop.sh after token refresh and the next
agent reads the plan to pick up where it left off.

Agent: human
Tests: N/A
Tests-Added: 0
TypeScript: N/A
2026-04-09 21:34:11 -04:00
paulh c49d127db1 Update FEATURES_UPDATE and NEXT_STEPS to reflect current state
FEATURES_UPDATE.md: rewrote from scratch — was a stub from February
describing only docs-writing activity. Now documents all implemented
features: CLM generation stack, account/letter config metadata, eSignature
browsing layer, infrastructure, and what is not yet built.

NEXT_STEPS_DOCGEN.md: expanded from CLM-launch-only scope to cover the
full Phase 2 eSignature envelope creation plan (tracking fields, createEnvelope
approaches, persistence, UI button) and Phase 3 additional letter types.

CURRENT_STATUS.md: fix two remaining absolute /home/paulh/... doc links.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:16:58 -04:00
paulh 546ffd7dcf Remove erroneous ClientCertificate from CLMs1NamedCreds
JWT signing is handled by the DocusignJWT external credential. The
ClientCertificate parameter was adding unnecessary mTLS configuration
that DocuSign's API does not require. Now matches CLMuatNamedCreds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:11:25 -04:00
paulh 8fb9df01db Retrieve AcctDemo_NamedCreds into source; add to manifest
SecuredEndpoint credential pointing to account-d.docusign.com, backed by
the DocusignJWT external credential. Referenced by DTC_CLM_Demo account
setting for ESignature_Auth_Named_Credential__c.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:01:23 -04:00
paulh 091b1870b6 Fix AcctDemo_NamedCreds note — exists in org, not yet retrieved to source
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:56:06 -04:00
paulh 148854ff1e Add retrieved/ and .codex to .gitignore; document manual credential setup
.gitignore:
- Add retrieved/ (org retrieve scratch metadata — not source of truth)
- Add .codex (Claude Code agent state)

SALESFORCE_SETUP.md:
- Add AcctDemo_NamedCreds to named credentials list with note that it must
  be created manually in the target org (not in source)
- Add "Manual post-deploy steps" section documenting AcctDemo_NamedCreds
  setup and the DocusignJWT external credential demo values (iss/sub/aud)
  that need to be replaced before use in a real org

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:51:03 -04:00
paulh 0ce516bbfc Fix LWC async bug, null guard, stale sample script; update manifest
LWC fixes:
- clmDocGenWorkbench: resetSelectionsToDefaults was a sync onclick handler
  calling async initializeDefaults without await — isBusy not set and errors
  silently dropped; made the method async and added await
- clmRequestPreview: loadPreview called from refreshAll (account/letter change
  handlers) without a recordId guard; a null appraiserCaseId would propagate
  to the Apex AuraHandledException; added early return with a user-facing message

manifest/package.xml:
- Was missing CLM_Account_Setting__mdt and CLM_Letter_Definition__mdt objects
  and all 17 custom metadata records
- Missing DocusignESignatureService and its test class
- Missing docusignEsignWorkbench and clmRequestPreview LWC components
- Missing NamedCredential section entirely (CLMs1*, CLMuat*, Esignature_Demo)
- Missing CLM Account Setting and Letter Definition layouts

scripts/apex/createSampleAppraiserCase.apex:
- Rewrote entirely; old version referenced the deleted Appraiser_Deficiency__c
  object, Sort_Order__c, Deficiency_Number__c as a string, and the deleted
  AppraiserCaseDocGenService class
- Now uses Appraiser_Case_Deficiency__c with correct field types
- Populates all appraiser identity/address fields added since original version
- Debug output uses AppraiserCasePayloadBuilder and CLMDocGenCallout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:50:57 -04:00
paulh fe337efe63 Update documentation to reflect current architecture
SALESFORCE_SETUP.md:
- Rewrite "What was added" to cover all current fields, metadata types,
  Apex classes, LWC components, named credentials, and permission sets
- Add DocusignESignatureServiceTest to the test run command

README.md:
- Replace absolute /home/paulh/... paths with relative ./FILE.md links

CLM_INTEGRATION.md:
- Pattern 1: replace wrong 3-arg trigger callout with correct Queueable pattern
  (triggers cannot make direct callouts)
- Pattern 2: mark LWC quick action as implemented (no longer a recommendation)
- Pattern 3: update REST resource to use CLMAdminService.generateDocument signature
- Payload/request/response: replace old pre-XML format with current
  documentxmlmergetasks JSON and XML structure
- Template design: replace Handlebars syntax with CLM XML merge description

NEXT_STEPS_DOCGEN.md:
- Mark Option B (LWC quick action) as complete
- Replace open-ended "what to confirm" with forward-looking guidance on
  extending to NOD, Education, and Intent to Remove letter types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:36:29 -04:00
paulh 45814dc2d5 Add CLMAdminService, DocusignESignatureService, and fix code review issues
New classes:
- CLMAdminService: UI-facing orchestration — account/letter settings from
  metadata, document generation, task status polling, file attachment,
  folder browsing; persists all CLM results to Appraiser_Case__c
- DocusignESignatureService: eSignature API browsing (accounts, templates,
  envelopes, login info, user info)
- CLMAdminServiceTest, CLMDocGenCalloutTest, DocusignESignatureServiceTest

Updated classes (AppraiserCasePayloadBuilder, CLMDocGenCallout):
- CLMDocGenCallout: full XML merge callout stack, task status polling,
  document download, recursive document href discovery, account-based
  endpoint building; HTTP_TIMEOUT made public
- AppraiserCasePayloadBuilder: formatMailingAddress made public so
  CLMAdminService can reuse it rather than duplicating the logic

Code review bug fixes:
- Fix null fields emitting literal "null" in generated XML — add safeValue()
  helper; String.valueOf(null) returns "null" so escapeXml's null guard
  never fired
- Fix unguarded inline SOQL in getCaseContext and getDocGenPreview — throws
  QueryException for missing records instead of AuraHandledException; now
  uses list query with isEmpty guard
- Remove duplicate formatAddress in CLMAdminService; delegate to
  AppraiserCasePayloadBuilder.formatMailingAddress
- Replace hardcoded 30000 timeout in performGet with CLMDocGenCallout.HTTP_TIMEOUT
- Remove duplicate JSDoc on getTaskStatus

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:36:16 -04:00
paulh 62b78faf1a Add new Salesforce metadata for account-based CLM and eSignature integration
- Appraiser_Case__c: appraiser identity/address fields, FHA case number,
  CLM tracking fields (task ID/URL/status), generated document fields,
  attached file fields, Letter_Sent_Date__c
- Appraiser_Case_Deficiency__c: Reference__c field, blank-record validation rule
- CLM_Account_Setting__mdt and CLM_Letter_Definition__mdt: per-account CLM
  and eSignature configuration with seeded records for DTC_CLM_Demo,
  DTC_IAM_Enterprise, DTC_HUD_Demo
- CLM_Environment_Setting__mdt: UAT/S1 environment defaults
- Named credentials: CLMs1NamedCreds, CLMs1Download, Esignature_Demo_NamedCreds
- LWC: clmDocGenWorkbench, docusignEsignWorkbench, clmRequestPreview
- Layouts, record page, permission sets, quick action, app, tabs, manifest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:35:59 -04:00
paulh 703fb0c0ba Remove legacy Appraiser_Deficiency__c object and AppraiserCaseDocGenService
Replaced by Appraiser_Case_Deficiency__c (master-detail, with Reference__c
field) and the XML-merge-based CLMDocGenCallout/CLMAdminService stack.
Also removes placeholder named credentials CLMNamedCred and CLMuatDownloadNamedCreds
superseded by the account-specific credential set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:35:42 -04:00
paulh e058dedb82 Create Appraiser Case custom record and DocGen service 2026-04-05 14:31:51 -04:00
paulh 1e532029fa Add Appraiser Review Letter template and XML merge data 2026-04-05 14:22:57 -04:00
paulh 63b1bfd758 Initial commit: Salesforce Appraiser Review Letter with DocuSign CLM integration 2026-04-03 12:13:59 -04:00