import { AlertTriangle, ArrowLeft, FileClock, ShieldAlert } from 'lucide-react' import { Link, useParams } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import { ToolHeader } from '../../components/ToolHeader' import { Panel } from '../../components/ui' import { request } from '../../lib/api' import { slateBrand } from './brand' import { useTrackedOpportunity } from './captureQueries' // THE AMENDMENT VIEW. Directive Section 4 item 11: an amendment FLAGS affected approved requirements for a // named human to accept, and nothing silently rewrites one. // // THE SCREEN IS BUILT AROUND THAT SENTENCE. It shows the version history so a reader can see that versions are // added and never edited, the alerts so they can see somebody was told, and the approved requirements reachable // from this opportunity so they can see WHAT IS AT STAKE. There is deliberately no button here that applies an // amendment to a requirement, because no such action exists: the requirement changes only by a human going to // the draft screen and making a new decision, which is the whole safety property. interface AmendmentPayload { versions: Array<{ version_number: number amendment_number: string source_version_label: string source_payload_hash: string fetched_at: string is_current: boolean }> alerts: Array<{ id: string alert_type: string severity: string title: string detail: string status: string created_at: string }> affected_requirements: Array<{ requirement_id: string draft_id: string labor_category: string clearance_level: string quantity: number source_scope_item_id: string source_scope_title: string }> } export function AmendmentView() { const { id = '' } = useParams() const opp = useTrackedOpportunity(id) const q = useQuery({ queryKey: ['slatematch', 'amendments', id], queryFn: () => request(`/opportunities/tracked/${encodeURIComponent(id)}/amendments`), enabled: !!id, }) const versions = q.data?.versions ?? [] const alerts = q.data?.alerts ?? [] const affected = q.data?.affected_requirements ?? [] return (
{/* Which opportunity this is. Every one of these screens is scoped to a single pursuit, and a reviewer arriving from a link needs to know which one before they start accepting things. */} {opp.data?.title &&

{opp.data.title}

} Back to the opportunity {q.isLoading &&

Loading the amendment history.

}

Versions are immutable. The database refuses an update to anything but the current flag and refuses a delete outright, so this list only ever grows.

{versions.length === 0 &&

No versions recorded yet.

}
    {versions.map((v) => (
  1. Version {v.version_number} {v.is_current && ( current )} {v.amendment_number && ( amendment {v.amendment_number} )} {v.source_version_label && {v.source_version_label}} {v.fetched_at.slice(0, 19)} payload {v.source_payload_hash.slice(0, 10)}
  2. ))}
{versions.length > 0 && versions.filter((v) => v.is_current).length !== 1 && ( // FINDING D9 LEFT A VISIBLE SCAR AND THIS IS IT. An opportunity with no current version, or two, is a // broken invariant, and it is surfaced rather than left for a background job to trip over again.

{versions.filter((v) => v.is_current).length} versions are flagged current. Exactly one should be. This is the invariant whose breach stopped amendment recording for this opportunity in July.

)}
{alerts.length === 0 &&

No amendment alerts for this opportunity.

}
    {alerts.map((a) => (
  • {a.severity} {a.title} {a.status}
    {a.detail &&

    {a.detail}

    }

    {a.created_at.slice(0, 19)}

  • ))}

These are live requirements the scoring engine matches against. An amendment FLAGS them; it never rewrites them. Changing one means a named human making a new decision on the draft screen.

{affected.length === 0 && (

Nothing has been promoted from this opportunity yet, so nothing is at risk.

)}
    {affected.map((r) => (
  • {alerts.length > 0 && } {r.labor_category} {r.quantity} needed {r.clearance_level}
    {/* THE LINEAGE, rendered so a flag can be walked back to the cited span it came from. */}

    derived from scope item {r.source_scope_title || r.source_scope_item_id.slice(0, 8) || 'not recorded'} {r.requirement_id ? ` , requirement ${r.requirement_id.slice(0, 8)}` : ''}

  • ))}
{alerts.length > 0 && affected.length > 0 && (

The source changed and {affected.length} approved requirement {affected.length === 1 ? ' is' : 's are'} derived from it. Review the scope, then decide. Nothing has been altered automatically.

)}
) }