diff --git a/src/App.jsx b/src/App.jsx
index f00e451..fcb00f6 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -6,7 +6,6 @@ import { PortfolioProvider } from './api/portfolio.jsx'
import Overview from './screens/Overview.jsx'
import Pipeline from './screens/Pipeline.jsx'
import Lead from './screens/Lead.jsx'
-import AddLead from './screens/AddLead.jsx'
export default function App() {
const { isAuthed } = useZino()
@@ -28,7 +27,6 @@ export default function App() {
one stage, usually empty, and somebody else's. */}
} />
} />
- } />
} />
} />
diff --git a/src/api/config.js b/src/api/config.js
index 49bd7b2..87403e2 100644
--- a/src/api/config.js
+++ b/src/api/config.js
@@ -276,8 +276,40 @@ export const DOC_SLOTS = {
export const LINE_FIELDS = {
gstin: 'sme',
udyam_no: 'sme',
- // entity_name is NOT listed: the form labels it "Business Name", but motor
- // leads carry one too — a company-owned vehicle has an owner with a name.
+ // entity_name is labelled "Business Name" on the form. A company-owned
+ // vehicle does have an owner with a name, so this is not strictly an SME
+ // field — but asking a motor renewal for a business name puts an empty box
+ // on the shortest form in the app, and the answer is already carried by
+ // customer_name in every motor lead we have. It is optional, so hiding it
+ // cannot block a submission, and an SME lead still gets it.
+ entity_name: 'sme',
+}
+
+/**
+ * Fields the form STAMPS rather than asks.
+ *
+ * Each is resolved by the prefill pipeline from the signed-in identity —
+ * Arjun IS Crestline Insurance Advisors, submitting through the agency door —
+ * so all three arrived filled and read-only-in-spirit, and the New lead form
+ * opened with three of its eleven boxes already answered by the system. That
+ * is three boxes of noise in front of the four that actually need a person.
+ *
+ * HIDDEN FROM THE FORM, STILL SENT. These are not decorative: source_channel
+ * is mandatory, and partner_code and rm_or_agent_id are what Intake attributes
+ * the lead on. So they are filtered at RENDER only — `fields`, which drives
+ * both validation and the payload, still holds them, and their prefilled
+ * values submit exactly as before. Filtering them out of `fields` instead
+ * would drop the attribution and 400 on the mandatory channel.
+ */
+export const STAMPED_FIELDS = new Set([
+ 'source_channel',
+ 'partner_code',
+ 'rm_or_agent_id',
+])
+
+/** Whether a field is stamped by prefill and so should not be drawn. */
+export function fieldIsStamped(fieldId) {
+ return STAMPED_FIELDS.has(baseFieldId(fieldId))
}
/**
diff --git a/src/components/ActivityForm.jsx b/src/components/ActivityForm.jsx
index 77e497e..8e564b3 100644
--- a/src/components/ActivityForm.jsx
+++ b/src/components/ActivityForm.jsx
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react'
import { useZino } from '../api/provider.jsx'
-import { baseFieldId, fieldApplies } from '../api/config.js'
+import { baseFieldId, fieldApplies, fieldIsStamped } from '../api/config.js'
import { describeError, describeValidation } from '../api/errors.js'
import FileField from './FileField.jsx'
import './ActivityForm.css'
@@ -135,13 +135,27 @@ export default function ActivityForm({ activityUid, instanceId, lead, onDone, on
// fields and is runnable from Contacted whatever the product is, so on an SME
// lead this would otherwise render a form with nothing in it and a live Submit
// button. Show the activity whole and let the operator see what it is asking.
- const applicable = schema ? schema.fields.filter((f) => fieldApplies(f.id, lead)) : []
+ //
+ // THE LINE CAN BE CHOSEN ON THE FORM ITSELF. On an INIT form there is no
+ // lead yet, so `fieldApplies` had nothing to filter on and every entry form
+ // asked a motor renewal for a business name. But the product line IS on that
+ // form, three boxes up — the person has already said "Motor" by the time the
+ // question is drawn. So visibility reads the live answer first and the saved
+ // lead second, and the form narrows as it is filled.
+ const effLead = (() => {
+ const live = schema?.fields.find((f) => baseFieldId(f.id) === 'product_line')
+ const chosen = live ? values[live.id] : undefined
+ if (!chosen) return lead
+ return { ...(lead || {}), product_line: chosen }
+ })()
+
+ const applicable = schema ? schema.fields.filter((f) => fieldApplies(f.id, effLead)) : []
// Filtering must never hide a field the workflow requires: `submit` sends only
// what is rendered, so a hidden mandatory field becomes a 400 naming something
// that is not on screen and cannot be filled. Hiding everything is the same
// failure in the large — it removes the activity rather than its noise, and
// Capture Motor Risk is twelve motor fields that stay runnable on an SME lead.
- const hidesMandatory = schema ? schema.fields.some((f) => f.mandatory && !fieldApplies(f.id, lead)) : false
+ const hidesMandatory = schema ? schema.fields.some((f) => f.mandatory && !fieldApplies(f.id, effLead)) : false
const fields = applicable.length && !hidesMandatory ? applicable : (schema?.fields ?? [])
/**
@@ -256,7 +270,15 @@ export default function ActivityForm({ activityUid, instanceId, lead, onDone, on
return (