diff --git a/src/api/config.js b/src/api/config.js
index 58f1e2e..e075119 100644
--- a/src/api/config.js
+++ b/src/api/config.js
@@ -119,7 +119,7 @@ const STATE_ACTIVITIES = {
],
'zk-state-qualified': [
{ uid: 'zk-act-contact', label: 'Log Contact', by: 'Engage AI', role: 'force' },
- { uid: 'zk-act-retry-call', label: 'Retry Call', by: 'Scheduled', role: 'again' },
+ { uid: 'zk-act-retry-call', label: 'Retry Call', by: 'Scheduled', role: 'force' },
],
'zk-state-contacted': [
{ uid: 'zk-act-request-docs', label: 'Request Documents', by: 'Engage AI', role: 'force' },
@@ -128,7 +128,7 @@ const STATE_ACTIVITIES = {
// be found and uploaded. Everything else here is the AI's own chain.
'zk-state-docs': [
{ uid: 'zk-act-collect-docs', label: 'Upload documents', by: 'you', role: 'do' },
- { uid: 'zk-act-doc-reminder', label: 'Send a reminder', by: 'Scheduled', role: 'again' },
+ { uid: 'zk-act-doc-reminder', label: 'Send a reminder', by: 'Scheduled', role: 'force' },
{ uid: 'zk-act-capture-motor', label: 'Capture Motor Risk', by: 'Engage AI', role: 'force' },
{ uid: 'zk-act-capture-sme', label: 'Capture SME Risk', by: 'Engage AI', role: 'force' },
{ uid: 'zk-act-advise', label: 'AI Cover Recommendation', by: 'Advisor AI', role: 'force' },
diff --git a/src/components/ActivityForm.jsx b/src/components/ActivityForm.jsx
index 5872860..e980b1e 100644
--- a/src/components/ActivityForm.jsx
+++ b/src/components/ActivityForm.jsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import { useZino } from '../api/provider.jsx'
-import { fieldApplies } from '../api/config.js'
+import { baseFieldId, fieldApplies } from '../api/config.js'
import { describeError, describeValidation } from '../api/errors.js'
import FileField from './FileField.jsx'
import './ActivityForm.css'
@@ -68,15 +68,36 @@ export default function ActivityForm({ activityUid, instanceId, lead, onDone, on
// whichever convention a pipeline is authored in, rather than breaking
// again the next time one is written the other way.
const pre = s.prefill_data || s.prefillData || s.field_defaults || {}
+ const seed = {}
if (pre && typeof pre === 'object') {
- const seed = {}
for (const f of s.fields) {
- const base = String(f.id ?? '').replace(/_\d+$/, '')
+ const base = baseFieldId(f.id ?? '')
const v = pre[f.id] ?? pre[f.uid] ?? (base ? pre[base] : undefined)
if (v !== undefined && v !== null && v !== '') seed[f.id] = v
}
- if (Object.keys(seed).length) setValues(seed)
}
+
+ // THE LEAD ALREADY KNOWS MOST OF THIS. The document form mirrors
+ // fourteen fields the record carries — registration, make and model,
+ // previous insurer, expiry, policy number, PAN — so the OCR can write
+ // into them. Rendered blank, they read as fourteen more things to type.
+ // Seed each from the lead by its base key, so an agent uploading for
+ // KA01MF6618 sees KA01MF6618 already there.
+ //
+ // Server prefill wins, then anything already typed. Files and generated
+ // ids are never seeded — a file reference is not a value to copy, and an
+ // id_gen is the platform's to issue. Only on an existing lead: an INIT
+ // form has no record behind it.
+ if (lead && instanceId) {
+ for (const f of s.fields) {
+ if (seed[f.id] !== undefined) continue
+ if (['file', 'ocr', 'id_gen'].includes(f.data_type)) continue
+ const v = lead[baseFieldId(f.id ?? '')]
+ if (v !== undefined && v !== null && v !== '' && typeof v !== 'object') seed[f.id] = v
+ }
+ }
+
+ if (Object.keys(seed).length) setValues(seed)
})
.catch((e) => { if (!dead) setError(e) })
return () => { dead = true }
diff --git a/src/layout/Shell.jsx b/src/layout/Shell.jsx
index 446d1d3..78e634f 100644
--- a/src/layout/Shell.jsx
+++ b/src/layout/Shell.jsx
@@ -48,6 +48,12 @@ export default function Shell() {
>
Overview
+
Unknown stage.
@@ -92,7 +104,9 @@ export default function Pipeline() {- {stage.kind === 'auto' + {isAll + ? 'Every lead not yet closed, across all stages.' + : stage.kind === 'auto' ? `Automated · ${stage.doing.toLowerCase()}` : stage.kind === 'end' ? 'Closed — retained for reporting.'