/* Control · Tasks — agent-driven task flows. Each task in the Control Tasks table maps to a scripted chat flow: the assistant opens with context, then hands the user an inline control (upload / survey / conflict pick / approval / checklist) that advances the flow and finally closes the task. Data only + the card renderers; the runner lives in chat_panel.jsx. */ const TF_DONE_NOTE = 'Task closed \u00b7 recorded in the hub\u2019s decision log'; window.TASK_FLOWS = { /* ── 1 · Fulfilling the model ─────────────────────────────────────────── */ 't-context': { title: '9 of 100 parameters unresolved', type: 'Missing context', steps: [ { statuses: ['Reading the Atlas revenue model\u2026', 'Checking mapped sources\u2026', 'Isolating the gaps\u2026'], answer: [ 'I\u2019m assembling the Project Atlas revenue model and ', { bold: '9 of 100 parameters are still unresolved' }, '. All nine trace to one gap: there is no Salesforce sales data for Q3 FY26 \u2014 closed-won amounts, discount depth and segment mix for the quarter.', { br: true }, 'Everything else is mapped, so this is the last blocker before the model can compute segment margin. Upload the Q3 bookings export and I\u2019ll take it from there.', ], card: { kind: 'upload', label: 'Drop the Salesforce Q3 FY26 bookings export', hint: '.xlsx or .csv \u00b7 read-only, stays in this hub', file: 'Salesforce_Q3_FY26_bookings.xlsx', alt: 'Connect Salesforce read-only instead', altReply: 'Connect Salesforce read-only and pull it yourself.', }, }, { statuses: ['Parsing Salesforce_Q3_FY26_bookings.xlsx\u2026', 'Mapping 9 parameters\u2026', 'Recomputing segment margin\u2026'], answer: [ 'Parsed 2,418 opportunity rows covering Jul\u2013Sep FY26. All nine parameters resolved: closed-won ARR $18.6M, average discount 11.4%, and segment mix across Enterprise, Mid-market and Channel.', { br: true }, 'The model is complete at 100 of 100 parameters and segment margin now computes without estimates. I\u2019ve added the export to the knowledge base and closed the task.', ], card: { kind: 'done', rows: [['Parameters resolved', '100 / 100'], ['Source added', 'Salesforce Q3 FY26 bookings'], ['Model status', 'Complete \u2014 no estimates']], note: TF_DONE_NOTE, }, complete: true, }, ], }, /* ── 2 · Tacit knowledge ──────────────────────────────────────────────── */ 't-tacit': { title: 'Deal-team roles undocumented', type: 'Tacit knowledge', steps: [ { statuses: ['Searching the hub for a governance document\u2026', 'Checking existing rules\u2026'], answer: [ 'I can\u2019t answer "who approves this model" from anything in the hub \u2014 there is no governance document, and the four rules I need don\u2019t exist yet. This knowledge only lives with you.', { br: true }, 'Four short questions and I\u2019ll write your answers into the model as rules the agents follow from then on.', ], card: { kind: 'survey', questions: [ { q: 'Who signs off on the final valuation model?', options: ['CFO \u2014 Eleanor Kwan', 'Deal lead \u2014 James Anderson', 'Both, in that order'] }, { q: 'Above what deal size does the board approve?', options: ['$5M', '$25M', '$50M'] }, { q: 'Who owns Salesforce data quality for diligence?', options: ['Revenue Ops', 'Finance', 'Deal team'] }, { q: 'Can draft models be seen by the whole hub?', options: ['Yes', 'Deal team only'] }, ], reply: 'Answered all four.', }, }, { statuses: ['Writing 4 rules\u2026', 'Validating against the model\u2026'], answer: [ 'Recorded. Four rules are now active in this hub: sign-off order, the $25M board threshold, Revenue Ops as Salesforce data owner, and draft visibility limited to the deal team.', { br: true }, 'Agents will apply them without asking again \u2014 the approval routing on the Atlas model already reflects the sign-off order.', ], card: { kind: 'done', rows: [['Rules written', '4'], ['Applies to', 'All agents in this hub'], ['Approval routing', 'Deal lead \u2192 CFO']], note: TF_DONE_NOTE, }, complete: true, }, ], }, /* ── 3 · Conflict resolution ──────────────────────────────────────────── */ 't-conflict': { title: 'Q3 gross margin conflict', type: 'Resolving conflict', steps: [ { statuses: ['Comparing Q3 margin across sources\u2026', 'Tracing the difference\u2026'], answer: [ 'Two sources report a different Q3 gross margin and I can\u2019t pick one on my own. The board pack says ', { bold: '62.4%' }, '; the figure derived from Salesforce and the GL says ', { bold: '58.9%' }, '.', { br: true }, 'The 3.5-point gap is one treatment difference: $1.9M of channel rebates that the board pack nets out of revenue and the GL books as cost of sales. Tell me which is canonical and why, and I\u2019ll hold every downstream metric to it.', ], card: { kind: 'conflict', options: [ { value: '62.4%', source: 'Q3 FY26 board pack \u00b7 p.14', detail: 'Rebates netted out of revenue' }, { value: '58.9%', source: 'Salesforce + GL \u00b7 derived', detail: 'Rebates booked to cost of sales' }, ], reasons: ['Matches how the board reads margin', 'Matches statutory reporting', 'Buyer requested GL-consistent figures'], reply: 'Use the board-pack figure \u2014 62.4%.', }, }, { statuses: ['Recording the decision\u2026', 'Re-pointing dependent metrics\u2026'], answer: [ '62.4% is now the canonical Q3 gross margin, with your reason attached, and the 4 dependent metrics have been re-pointed to it \u2014 segment margin, margin trend, the bridge in the board pack and the diligence summary.', { br: true }, 'If a source contradicts it later I\u2019ll flag the source rather than reopen the question.', ], card: { kind: 'done', rows: [['Canonical value', 'Gross margin Q3 \u2014 62.4%'], ['Dependent metrics repointed', '4'], ['Conflicting source', 'Flagged, not overwritten']], note: TF_DONE_NOTE, }, complete: true, }, ], }, /* ── 4 · Pre-update review ────────────────────────────────────────────── */ 't-preupdate': { title: 'Salesforce report awaits review', type: 'Pre-update review', steps: [ { statuses: ['Reading the new Salesforce export\u2026', 'Diffing against the live model\u2026'], answer: [ 'The weekly Salesforce report landed 8 minutes ago. It is clean and parses, but it moves three metrics leadership reads, so I\u2019ve held the update rather than recomputing quietly.', { br: true }, 'Nothing changes until you approve.', ], card: { kind: 'confirm', buttons: [ { label: 'Show me the 3 changes', reply: 'Show me the 3 changes first.', primary: true }, { label: 'Approve without review', reply: 'Approve the update.', skipTo: 2 }, ], }, }, { statuses: ['Preparing the diff\u2026'], answer: ['Here is what the update would change. Two moves are within normal weekly variance; pipeline coverage crossing below 3.0x is the one worth a look.'], card: { kind: 'diff', rows: [ { metric: 'ARR', before: '$41.2M', after: '$41.6M', delta: '+$0.4M' }, { metric: 'Win rate (TTM)', before: '24.8%', after: '23.6%', delta: '\u22121.2 pts' }, { metric: 'Pipeline coverage', before: '3.1x', after: '2.8x', delta: 'below 3.0x', warn: true }, ], buttons: [ { label: 'Approve update', reply: 'Approved \u2014 update the model.', primary: true }, { label: 'Hold for now', reply: 'Hold it until the pipeline review.', hold: true }, ], }, }, { statuses: ['Applying the approved report\u2026', 'Recomputing 3 metrics\u2026'], answer: [ 'Model updated from the approved report. Pipeline coverage is flagged at 2.8x on the diligence dashboard so it is visible in the next read, and the report is logged as the source of the change.', { br: true }, 'Next weekly sync will pause for review the same way.', ], card: { kind: 'done', rows: [['Metrics recomputed', '3'], ['Flagged for attention', 'Pipeline coverage 2.8x'], ['Approved by', 'You \u00b7 just now']], note: TF_DONE_NOTE, }, complete: true, }, ], }, /* ── 5 · Incomplete workflow ──────────────────────────────────────────── */ 't-workflow': { title: 'Q3 close audit paused', type: 'Incomplete workflow', steps: [ { statuses: ['Loading the Q3 close audit run\u2026', 'Checking where it stopped\u2026'], answer: [ 'The Q3 close audit stopped three days ago after step 2, on ', { bold: 'reconcile intercompany balances' }, '. Nothing is blocking it \u2014 the run simply wasn\u2019t resumed.', { br: true }, 'Five steps remain. Three are mine and run unattended; two need your sign-off. Resume and I\u2019ll work down the list and stop at each sign-off.', ], card: { kind: 'checklist', steps: [ { label: 'Lock the Q3 GL period', owner: 'agent', done: true }, { label: 'Pull trial balance from the GL', owner: 'agent', done: true }, { label: 'Reconcile intercompany balances', owner: 'agent' }, { label: 'Match 4 unmatched JV transactions', owner: 'agent' }, { label: 'Confirm the $1.9M rebate treatment', owner: 'you' }, { label: 'Recompute segment margin', owner: 'agent' }, { label: 'Sign off the close pack', owner: 'you' }, ], resumeLabel: 'Resume workflow', reply: 'Resumed and signed off both steps.', }, }, { statuses: ['Closing out the run\u2026', 'Writing the audit trail\u2026'], answer: [ 'Q3 close audit is complete \u2014 7 of 7 steps, with your two sign-offs recorded against the rebate treatment and the close pack.', { br: true }, 'The audit trail is attached to the Q3 close record; the same workflow will start again on the first of the month.', ], card: { kind: 'done', rows: [['Steps complete', '7 / 7'], ['Your sign-offs', '2 \u00b7 recorded'], ['Audit trail', 'Attached to Q3 close']], note: TF_DONE_NOTE, }, complete: true, }, ], }, }; /* ══════════════════ card renderers ══════════════════ */ const { useState: tfState } = React; function TfIcon({ name }) { const p = { up: 'M12 16V4M7 9l5-5 5 5M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2', check: 'M20 6 9 17l-5-5', file: 'M14 3v5h5M6 3h8l5 5v13H6z', warn: 'M12 8v5M12 16.5v.5M10.3 3.9 2.6 17.4A1.6 1.6 0 0 0 4 19.8h16a1.6 1.6 0 0 0 1.4-2.4L13.7 3.9a1.6 1.6 0 0 0-2.8 0z', arrow: 'M5 12h14M13 6l6 6-6 6', }[name]; return ; } function TfUpload({ card, onAction }) { const [state, setState] = tfState('idle'); if (state === 'sent') return