# DIRECTIVE AMENDMENTS 1 THROUGH 5, CONSOLIDATED Companion to docs/CLAUDE_CODE_BUILD_DIRECTIVE.md. Generated 27 July 2026. This file supersedes the five individual amendment files. Conflicts are pre resolved: Amendment 3's corrections are already applied inside the Amendment 2 content below. There is nothing to reconcile. Apply this file and the directive together as the complete work order. -------------------------------------------------------------------------------- 0. AUTONOMOUS APPLICATION PROTOCOL -------------------------------------------------------------------------------- 1. Read order: CLAUDE.md, docs/CLAUDE_CODE_BUILD_DIRECTIVE.md, this file, docs/BUILD_STATE.md. Then apply. 2. Record "amendments 1 through 5 accepted, consolidated" in BUILD_STATE with the date and this file's path. 3. If individual amendment files exist under docs, move them to docs/archive. Exactly one amendment source may exist: this file. 4. Merge map: Amendment 1 appends to directive Section 0 as an environment rule. The slate approval lifecycle merges into Phase 3 and Gate 3. Desk integration, publishing, the Import Center, the Candidates page, and the desk dataflow merge into Phase 5 and Gate 5. The canonical dataflow becomes a permanent directive appendix. Acceptance items 25 through 35 append to directive Section 11. Task T1 registers as standalone work outside the phase gates. 5. Passed gates are never reopened. If an item conflicts with work already completed, record the conflict in BUILD_STATE, choose the smallest change that satisfies both, and note it. If no such change exists, stop and surface it. 6. Autonomous operation: proceed phase by phase without waiting for permission. Verify every gate against staging, record evidence in the ledger, and continue. Surface to Joseph only for these four things: any Phase 0 human blocker not yet recorded in the ledger, the vhost confirmation for Task T1 if the target is ambiguous, review of the two nginx location blocks before anything touches the live fg-talent.com vhost, and the Gate 6 production cutover. 7. Every directive rule stands unchanged: staging only until Gate 6, meaning missionmatch_staging on M4 port 5432 (see the corrected location note directly below); the candidate scoring engine is frozen; forced RLS and organization_id on every tenant table; extend, never build beside; fail closed; no Python; no dashes in written output, hyphens only in code identifiers, protocol headers, and official designations. -------------------------------------------------------------------------------- AMENDMENT 1: ENVIRONMENT RULE -------------------------------------------------------------------------------- CORRECTED LOCATION, ratified by Joseph 28 July 2026. This file originally named staging as missionmatch_staging on megamind-agi port 5433. That database exists but is an EMPTY SHELL: zero organizations, zero candidates, and a goose_db_version table the app role cannot even read. IT MUST NOT BE USED. The functioning staging, and the only one this directive means, is: missionmatch_staging on M4, 100.94.8.94, port 5432 That is the database the live mm-api-staging service on 127.0.0.1:8097 serves, it carries real working data, and it is the only staging target that can satisfy a gate, because a gate requires an end to end check through a live authenticated API and a rendered screen. Every migration, every live database verification, and every end to end check through Phase 5 runs against missionmatch_staging on M4 port 5432. The production tenant database is touched only at Gate 6, and only after the backup and restore test passes. If any task appears to require production before Gate 6, stop and record the conflict in BUILD_STATE instead of proceeding. The three Phase 0 human blockers, revoking the exposed OpenAI key, placing the fresh project scoped key on M4 as openai_api_key root owned 0600, and starting the SAM.gov system account application, were recorded as ledger events when Joseph completed them. If any of the three is absent from the ledger, do not enable anything external and surface it. -------------------------------------------------------------------------------- AMENDMENT 2, AS CORRECTED BY AMENDMENT 3: WORKFLOW COMPLETION AND PUBLIC SURFACES -------------------------------------------------------------------------------- 2.1 DECISIONS RECORDED 1. Slate approval becomes a lifecycle: proposed, approved, withdrawn. Approval writes into proposal staffing links and readiness. Withdrawal exists, requires a reason, and is fully audited. Amends Phase 3. 2. screenMATCH and resumes wire into the recruiting desk through the shared candidate record and a requisition to requirement bridge. The frozen engine is reused through that bridge, never duplicated. Amends Phase 5. 3. The primary public jobs surface is the tenant company's own website. fg-talent.com is the first and the reference implementation. For a mapped tenant, candidates never see the missionMATCH domain. 4. Serving pattern: nginx on Bubbles proxies fg-talent.com/careers/ to the mm_api public jobs handler, which renders complete server side HTML from Go templates, branded for the tenant. Crawlers and visitors receive real HTML in the initial response. No client side rendering of job content anywhere. This is chosen over static file generation because it serves the same real HTML while updating the instant a recruiter publishes or fills an order, one rendering path instead of two. 5. Tenant site mapping, configuration not code: tenant_slug, public_base_url (https://fg-talent.com/careers), brand template, consent notice reference. A mapped tenant's jobs path on the missionMATCH domain issues a 301 to the tenant domain. Unmapped tenants may use the app domain hosted jobs page. 6. Apply is same origin on the tenant domain. fg-talent.com/careers/apply proxies to the mm_api apply intake. A submission creates or dedupe matches a candidate and creates an application in the applied stage in the FG Talent tenant, source career_site, consent event stored with notice version, honeypot plus an nginx limit_req zone on the apply path modeled on the existing mm_auth zone. 7. Nothing is ever posted to Google. Indexing follows the house SEO rules and nothing else: a careers sitemap section regenerated on every publish and unpublish, internal links from the careers index and site navigation, GSC Request Indexing, and the URL Inspection API. JobPosting JSON-LD remains on each job detail page as standard on page schema, one block per canonical URL, mirroring the visible content, because it makes the fg-talent.com pages themselves surface in search and answer engines. That is the entire role Google plays. 8. Expiry discipline: on fill, close, or validThrough passing, the page unpublishes, the sitemap entry drops, and the markup is gone, enforced by cmd/jobs-expiry-sweep, idempotent like everything else. 9. FG Talent content rule, enforced in template and in test: only Patricia Cox and Brian Atwood may appear anywhere on the public site or in schema. Tom and Glennette are excluded from every page, every JSON-LD block, every hiringOrganization contact, and every authored by field. hiringOrganization is FG Talent Partners. 10. Public surface hygiene: published fields only, never bill rates, margins, internal notes, or client names without the per requisition flag; tenant resolved by slug only, never by organization id; unknown slug returns 404 with nothing leaked; zero EEO adjacency on any public surface. 11. The marketing site login button is standalone Task T1, executed on the Bubbles vhosts, outside the phase gates and outside the missionMATCH repo. 12. The client portal read surface is deferred to fast follow, but its data model, client submittals with feedback and reason codes, ships now in Phase 5, so the portal later is a rendering task, not a migration. 13. Pay range fields on publish are optional, but the publish screen warns when the posting location or remote eligibility touches a state requiring a range in the posting: California, Colorado, Hawaii, Illinois, Maryland, Massachusetts, Minnesota, New Jersey, New York, Vermont, Washington, and the District of Columbia. 14. Automated candidate outreach on status changes is deferred to fast follow. Status changes create alerts and draft notifications a human sends. Deterministic triggers only. 2.2 TASK T1: MARKETING SITE LOGIN BUTTON 1. Enumerate the nginx vhosts on Bubbles and identify where missionMATCH is marketed publicly. The application lives at https://missionmatch.thatwebhostingguy.com, so the button belongs on the marketing surface, not inside the app. 2. If the target is ambiguous, list the candidate vhosts for Joseph in one message and wait for his pick. Do not guess on a production website. 3. Add a prominent Log in button in the site header and hero linking to https://missionmatch.thatwebhostingguy.com. Static HTML, CSS, and vanilla JS, brand consistent, no framework, no Python. 4. If no marketing page exists, say so and build a single branded page, hero, product line summary, and Log in, at the vhost Joseph names. 5. Verify rendered in a browser over HTTPS before recording done. 2.3 AMENDMENT TO PHASE 3: SLATE APPROVAL LIFECYCLE 1. Slate member decision becomes a lifecycle with columns on the existing slate member record: status in proposed, approved, withdrawn, plus approved_by_user_id, approved_at, withdrawn_by_user_id, withdrawn_at, and withdrawal_reason. withdrawal_reason is required on every withdrawal and stored. 2. Approve, one transaction taking FOR UPDATE on the member row: set status and stamps, and where the slate is linked to a proposal, increment proposal_staffing_links.approved_count. Audit through OnTx. The approval appears in the proposal Staffing tab, readiness inputs, and slate exports with who and when. 3. Withdraw, same transaction discipline: requires the reason, sets status and stamps, decrements approved_count, audits, and flags the latest readiness snapshot stale. Withdrawal never deletes anything. 4. Re approval after withdrawal is allowed. The audit trail carries the full sequence. 5. Both actions use the existing slate decision capability. Both notify the capture owner and proposal owner through the alerts module. 6. UI: approve and withdraw buttons on the slate member row, withdraw opens a reason modal, the row shows current status with the latest stamp. GATE 3 ADDITIONS: approve, withdraw, and re approve leave approved_count exactly correct under an eight way race, proven by racing it. A withdrawal without a reason is rejected by the API, not just the form. A withdrawal flips readiness staleness and the next snapshot reflects the reduced coverage. The full sequence is visible in the audit trail. 2.4 AMENDMENT TO PHASE 5: DESK INTEGRATION A. Requisition to requirement bridge. Requisitions gain requirement_id. Creating a job order offers two paths: link an existing requirement, or create and link one using the same structured requirement fields the platform already scores against. The frozen engine is reached only through this bridge. Editing the linked requirement after screenings exist marks those screening results stale, never silently. B. Resume pipeline. Resume upload on the candidate record and through the apply intake: sha256, versioned, stored through internal/platform/storage, current flag, priors retained. Parsing runs through docextract and extraction into draft profile suggestions: skills, certifications, experience entries, and clearance indicators always labeled clearance intelligence, self reported. Suggestions are accepted or edited by the recruiter, never silently applied. Duplicate detection on candidate create and on apply matches email and phone and prompts to open or merge. C. Screen from the desk. On an application row, a Screen action runs the screenMATCH evaluation against the requisition's linked requirement. The result, score, band, caps applied, engine version, timestamp, stores on the application and renders in the pipeline. Re screening keeps history. A stale badge shows when the requirement changed after the screening ran. screenMATCH's queue lists desk originated screenings. 2.5 AMENDMENT TO PHASE 5: PUBLISHING TO THE TENANT WEBSITE 1. Requisition publish workflow. Visibility: internal_only or published. Public label: open, on_hold, filled, closed. The publish checklist requires title, public description, location or remote with explicit applicant location requirements, employment type (arrays supported, contract to hire is CONTRACTOR plus FULL_TIME), a validThrough date, and apply enabled. Pay range and benefits description are optional with the state warning from decision 13. 2. mm_api public jobs handler renders three things per mapped tenant: the careers index at public_base_url, one canonical detail page per published open job at public_base_url plus a stable job slug, and the apply endpoint. Canonical link tags point at the fg-talent.com URLs. Cache headers allow nginx to cache briefly, purged on publish and unpublish. Each detail page carries exactly one JobPosting JSON-LD block mirroring the visible content: title, description, datePosted, validThrough, hiringOrganization as the tenant, jobLocation or remote with applicantLocationRequirements, employmentType, optional baseSalary, and identifier as a PropertyValue holding the internal requisition id. No JobPosting markup on the list page. 3. The nginx change on the fg-talent.com vhost is two location blocks matched to that vhost's conventions: one proxying /careers/ to the mm_api upstream with the tenant slug fixed server side, one for /careers/apply with the rate limit zone. Claude Code drafts the exact blocks, Joseph reviews before they touch the live vhost, and the reload is verified with the zero 5xx sweep. The careers index gets an internal link from the main navigation as part of the vhost change. 4. The brand template for FG Talent matches the existing site design language, header, footer, typography, colors, so the careers section reads as native. 5. Embeddable feed. GET /jobs/{tenant_slug}/feed.json returns published open jobs, and a small vanilla JS embed snippet renders them on any other page, documented. For a mapped tenant the canonical destination is always the proxied careers page. 6. Apply intake, minimal: name, email, phone optional, resume upload, and a consent checkbox rendering the tenant's configured notice text from the Phase 4 notice system. Submission creates or dedupe matches a candidate, creates an application in the applied stage, records source career_site, stores the consent event with timestamp and notice version. Honeypot plus rate limiting. Rollout beyond FG Talent is one mapping row and one nginx block per client site. 2.6 AMENDMENT TO PHASE 5: DESK WORKFLOW ADDITIONS 1. Structured intake brief on every job order, three fixed blocks: role context, candidate profile, and submission logistics, where logistics means fee or rate terms, required submittal format, client feedback SLA, interview process, and the approval contact. Sourcing from an incomplete brief shows a warning, not a hard block. 2. Pipelines per placement type. Job order type, permanent, contract, contract to hire, temp, selects the stage template automatically. 3. Client submittal records as explicit steps distinct from internal submittal: packet reference, submitted_at, client feedback text, a feedback reason code, and a feedback SLA timer that ages visibly. This is the data model the future client portal renders. 4. Reason taxonomy on every rejection and every backward stage move, selected from a small configurable list plus free text. Reasons feed the intake quality loop and the segregated adverse impact reporting path, through the compliance role only, never the other direction. 5. Days in stage aging on the pipeline board, thresholds configurable per tenant, default flag when interview stage aging passes fifteen days. 6. Wire the existing activities and tasks tables into every record surface: notes timeline and tasks with owners and due dates on candidates, clients, requisitions, applications, and placements. 7. Talent pools and saved searches: named candidate lists per recruiter and team, add from any candidate list, saved search definitions, so a repeat job order starts from the last search instead of zero. 8. Status triggered alerts through the alerts module: stage change, client feedback recorded, offer accepted or declined, assignment end approaching. Drafted notifications, human send, per decision 14. 9. Offers completed: status enum with extended, accepted, declined stamps and a decline reason. Placement creation carries worksite, pay rate, bill rate, start date, and approval contact forward from the order and offer without retyping. 10. Optional requisition approval chain per client: when a client is flagged as requiring it, a manager approval step gates the order going active. 11. Client specific submittal requirements live on the client record, format notes and process notes, surfaced automatically at submittal time. 2.7 FAST FOLLOW ADDITIONS Append to the directive's fast follow list: the client portal rendering the submittal and feedback model, read only, per client contact authentication; automated candidate engagement sequences on status triggers once a sending policy is decided; VEVRAA ESDS posting reusing the publish pipeline as its source of truth; knockout questions and reference check records on applications; a placement start onboarding checklist; and requisition and placement history import. 2.8 GATE 5 ADDITIONS, PUBLISHING AND DESK 1. Publish a job order in recruitMATCH and load it at https://fg-talent.com/careers/ and its detail URL. curl shows the full job content in the initial HTML response, no JS execution required. 2. The detail page carries exactly one JobPosting JSON-LD block that mirrors the visible content and passes the Rich Results test. 3. Submit the apply form from fg-talent.com: a candidate and an application exist in the FG Talent tenant, stage applied, source career_site, consent event stored with notice version, and the duplicate check fires on a repeat email. 4. Fill the order: the detail page is gone, the index no longer lists it, the sitemap entry is removed, and the markup is nowhere. 5. The missionMATCH domain path for the FG Talent slug issues a 301 to fg-talent.com. 6. Page and schema contain Patricia Cox and Brian Atwood only. A test asserts the strings Tom and Glennette appear nowhere in rendered output or JSON-LD. 7. Unknown slug returns 404 with nothing leaked, and the apply rate limit answers 429 under the race. 8. The careers sitemap section regenerates on publish and on unpublish, and GSC Request Indexing is exercised once manually and recorded. 9. The feed renders on a test page. 10. Screen from an application stores a banded result and goes stale when the requirement changes. Resume parse produces suggestions and never overwrites. Duplicate detection fires on a known email. 11. An intake brief saves with all three blocks. A client submittal records feedback with a reason code and its SLA timer ages. A rejection carries a taxonomy reason. An accepted offer flows into a placement carrying rates forward. 2.9 ACCEPTANCE ADDITIONS 25. Slate approval and withdrawal maintain correct counts under race, and every withdrawal carries a stored reason. 26. Public jobs surfaces expose only published data, resolve tenants by slug only, and pass Rich Results validation on every live posting. 27. Expired or filled postings drop their markup immediately, verified by the sweep job's test. 28. Apply intake stores a consent event with notice version for every submission. 29. Desk screenings reach the engine only through the requisition to requirement bridge, and the engine diff remains empty. -------------------------------------------------------------------------------- AMENDMENT 4: UPLOADS AND THE IMPORT CENTER -------------------------------------------------------------------------------- 4.1 DECISIONS RECORDED 1. One upload subsystem, three entry points: the candidate record, the recruitMATCH Import Center, and screenMATCH screen from resume. Parsing, deduplication, storage, and versioning exist in exactly one internal path that all three call. The apply intake uses the same path. 2. Every bulk import is staged, never direct. Files land in import_batches and import_rows, then validate, then preview, then a human commit writes live records. Extract, draft, review, approve, promote. 3. Import types shipping in Phase 5: single resume, resume bundle as multiple files or one zip, candidate spreadsheet as CSV or XLSX, and clients with contacts spreadsheet. 4. Protected class columns are rejected at validation, by name pattern and content sniffing: race, ethnicity, gender, sex, disability, veteran status, and kin. EEO and self identification data never enters through an import. The segregated compliance path is the only door. 5. Every imported candidate carries source import with a batch reference, and committing a batch requires a first party attestation checkbox, the tenant affirming the data was collected by their organization from the candidates directly. The attestation, who, and when are stored on the batch. 6. File rules. Resumes: pdf, docx, txt, rtf, legacy doc rejected with a clear resave message. Data: csv, xlsx. Bundles: zip only under the archive safety rules. Size caps and per batch row caps are configuration with sane defaults. 7. Processing is asynchronous through a job binary. The UI shows live progress and per row outcomes. Partial success is normal. Batches are idempotent and resumable: every row records its action, reruns skip completed rows. 4.2 DATA MODEL All tables carry the standard invariants. import_batches: organization_id, id, kind, status, source_file_name, storage_key, sha256, size_bytes, row_count, created_count, merged_count, skipped_count, failed_count, dedupe_policy, mapping_id, attestation_checked, attestation_user_id, attestation_at, created_by_user_id, started_at, completed_at, created_at. kind enum: resume_single, resume_bundle, candidates_sheet, clients_sheet. status enum: uploaded, validating, ready_for_review, committing, completed, completed_with_errors, failed, cancelled. dedupe_policy enum: prompt, merge, skip, create. import_rows: organization_id, id, batch_id, row_number, source_file_name, raw_content_ref, parsed_payload, validation_errors, dedupe_match_candidate_id, action, created_candidate_id, created_client_id, created_contact_id, error_code, processed_at. action enum: pending, created, merged, skipped, failed. Nothing here is a live record until commit writes one and stores its id back on the row. import_mappings: organization_id, id, kind, name, column_map, created_by_user_id, created_at, updated_at. Saved column mappings so a recurring spreadsheet format maps once. Resume storage and versioning reuse the candidate record model: sha256, versioned, current flag, priors retained, bytes through internal/platform/storage. 4.3 IMPORT CENTER, IN recruitMATCH 1. Upload screen: import type picker, drag and drop with a file picker, multiple files for bundles, single zip accepted, live progress, allowlist and size enforcement with clear per file errors. 2. Mapping screen for spreadsheets: source columns to candidate or client fields, automatic suggestion by header name, saved templates offered on header match, required field indicators, protected class rejection surfaced here with the offending columns named. 3. Review screen: counts by outcome, validation errors per row, dedupe resolution with the batch policy as default and per row override, matches shown side by side with the incoming row. 4. Commit: attestation checkbox, then asynchronous commit with live progress, final counts, and a per row error export through csvsafe. 5. Batch history: every batch with status, counts, uploader, drill in to rows. Cancellable before commit. Nothing about a committed batch is ever deleted. 6. Quick add stays: the single candidate form with inline resume upload, wired to the same subsystem. 4.4 screenMATCH ADDITIONS 1. Screen from resume, single: upload one resume inside screenMATCH, parse to draft profile, dedupe prompt on match, recruiter confirms create or use existing, selects the requirement, evaluation runs. Result stores with engine version and timestamp. Candidate carries source resume_upload. 2. Bulk screen against one requirement: upload a resume set or zip, a resume_bundle batch is created with the requirement attached, and on commit every created or matched candidate is evaluated against it. The screening queue fills with banded results, failures listed per file, nothing uncommitted is ever scored. 3. Archive safety wherever zip is accepted: list entries first, enforce per entry allowlist and size cap, cap entry count, reject nested archives, reject path traversal. Extraction only after the listing passes. 4. The frozen engine is reached only through the existing evaluation path. 4.5 PROCESSING 1. cmd/import-process: claims a batch, parses, validates, computes dedupe candidates, and executes commit, each step bounded, observable, audited, idempotent by row action, following the sam-sync and queue conventions. 2. Parsing through docextract and extraction. Spreadsheets parse in Go. Per row failures never abort the batch. 3. Large file behavior tested: a batch at the row cap completes with memory bounded through streaming reads. 4.6 GATE 5 ADDITIONS, IMPORTS 1. Commit a three file resume bundle: three candidates exist with parsed suggestions, sources read import, each traces to batch and row. 2. A planted duplicate triggers the dedupe prompt and a merge produces one candidate, not a twin. 3. A spreadsheet with a protected class column is rejected at validation with the column named, and nothing reaches a live table. 4. A five hundred row candidate spreadsheet commits with correct counts, per row lineage, and a clean error export. 5. Kill cmd/import-process mid commit and rerun: the batch completes with no duplicates, proven by counts. 6. Screen from resume produces a stored banded result and the dedupe prompt fires on a known email. 7. A bulk screen fills the screening queue and lists the one deliberately corrupt file as failed. 8. A zip with a path traversal entry and a zip with a nested archive are both rejected at listing. 9. Every commit stores the attestation with user and timestamp. 10. An uncommitted batch is invisible to candidates, search, matching, and slates, proven by query. 4.7 ACCEPTANCE ADDITIONS 30. No import writes a live record except through a committed batch, and every imported record carries batch and row lineage. 31. Protected class data cannot enter through any import path, proven by the rejection tests. 32. Import batches are idempotent under rerun and partial failure, with counts that always reconcile to rows. -------------------------------------------------------------------------------- AMENDMENT 5: THE CANDIDATE SPINE AND THE DESK DATAFLOW -------------------------------------------------------------------------------- 5.1 THE CANONICAL DATAFLOW, PERMANENT DIRECTIVE APPENDIX One candidate spine. One linking record. Everything hangs off it. INTAKE CANDIDATE WORK apply on fg-talent.com \ / desk pipeline Import Center bulk \ / (applications) screenMATCH resume > candidates table < proposal slates quick add on the desk / one record per person \ screenings (all paths dedupe) / all tools, same spine \ pools, searches THE LINKING RECORD: application (candidate x requisition) exactly one active application per candidate per requisition requisition (job order, openings count, linked requirement) | | add to job order (from match, search, pool, or manual) v application: prescreen -> internal submittal -> client submittal -> interview -> offer -> placed or out at any stage, always with a reason code | | offer accepted v placement takes a seat under the existing FOR UPDATE seat lock | v JOB ORDER UPDATES ITSELF stage counts derive live on the order last seat placed flips status to filled in the same transaction remaining active applications become filled_by_another, notified filled unpublishes the fg-talent.com page via the expiry sweep a fall off frees the seat, reopens the order, alerts the owner, and never republishes without a human confirming | v placement end approaching -> redeployment alert -> candidate returns to the available pool -> the spine loops Both match directions use the same frozen engine: a job order ranks candidates, and a candidate ranks open job orders, both reading through the requisition to requirement bridge. screenMATCH is the deep evaluation of one pairing, stored on the application. slateMATCH is the proposal branch off the same spine, and a person may sit on a slate and in a desk pipeline at once because both point at one candidate record. 5.2 DECISIONS RECORDED 1. One candidate spine. The missionMATCH command center Candidates screen and the new desk page read the same records. Shared candidate profile components are extracted into a shared frontend directory and composed by both surfaces. Nothing candidate shaped is duplicated per tool. 2. recruitMATCH gains a Candidates page in its navigation, gated by the recruitmatch entitlement. 3. Candidate search on the page is deterministic SQL: the existing hybrid fusion, tsvector rank with pgvector cosine joined by reciprocal rank fusion, exposed as a repository query with structured filters. The AI Ask path is untouched and separate. 4. Reverse matching runs the frozen engine, one candidate against the linked requirement of every open requisition. Orders without a linked requirement appear as unmatchable with a fix it link to the bridge. Every computed pairing persists with score, band, engine version, and computed_at, and goes stale when the requirement or the candidate profile changes after computation. 5. Add to job order creates the application. Exactly one active application per candidate per requisition, enforced by a partial unique index over non terminal statuses. Adding a candidate whose prior application on that order ended requires an explicit reopen with a taxonomy reason. 6. Applications record how they began: added_from in apply, import, match, search, pool, manual, screen. When added from match, the score snapshot, band, and engine version at add time are stored on the application. 7. The default stage template gains internal_submittal and client_submittal as explicit stages. Existing stage values are never renamed and never destroyed; the template extends, historical data stands, derive.go and analytics read the extended set. Placement type templates build on this default. 8. Job order status is a state machine: draft, open, on_hold, filled, closed. Filling the last seat flips open to filled automatically inside the placement transaction the seat lock governs. A fall off frees the seat and flips filled back to open automatically, with an alert. Manual transitions remain, and every transition, automatic or manual, is audited with its cause. 9. filled_by_another is a distinct application outcome, not a rejection. When an order fills, remaining active applications move there in the same transaction, their candidates flagged available, owners notified through alerts. 10. Republishing after a fall off requires a human confirm on the requisition. The page never reappears on fg-talent.com silently. 5.3 THE CANDIDATES PAGE, IN recruitMATCH 1. Roster list: name, headline or current title, clearance intelligence level, top skills, location, availability, source, last activity, active pipelines count, pools. Sortable, virtualized. 2. Filters: clearance intelligence level, skills, certifications, location and radius or remote, availability window, source, pool, has resume, last activity age. Free text runs the fusion query. Saved searches apply here, save and rerun. 3. Bulk actions on selected rows: add to pool, add to job order, export through csvsafe. 4. Candidate detail, composed from shared components, tabs: Profile (clearance intelligence always labeled self reported), Resumes (version list, inline viewer, download, upload new version), Screenings (every screenMATCH result with engine version, band, and stale badges), Pipelines (every application across orders with client, order, stage, status, aging), Activity and Tasks, Pools. 5. Detail actions: Match to open orders, Add to job order, Screen against an order, Add to pool, Edit profile, Upload resume. 5.4 REVERSE MATCH, CANDIDATE TO OPEN ORDERS 1. Match to open orders opens a ranked list: every open requisition with a linked requirement, scored by the frozen engine, showing band chip, score, client, order title, openings remaining, deadline or aging, and whether this candidate already has an application there. 2. Row actions: Add to pipeline, creating the application with the match snapshot, and Screen now, running the full screenMATCH evaluation on the pairing. Multi select add supported. 3. Unmatchable orders list at the bottom with a link opening the bridge flow. 4. Determinism: same candidate and same open orders produce the same ranking every run, decimal arithmetic, no model in the loop. Stale pairings recompute on open; persisted history is never overwritten. 5.5 ADD TO JOB ORDER, MECHANICS 1. One transaction: FOR UPDATE on any existing application row for the pair, insert or reopen, write added_from and the snapshot when present, write the activity, audit through OnTx. Eight racing adds produce one application. 2. Requisition list and detail show live stage counts, in pipeline, internal submittal, client submittal, interview, offer, placed, and out, derived by indexed query, plus openings remaining from placements. Stat tiles click through to the filtered pipeline. 3. Client detail shows its orders with the same counts, so find a candidate, match them, add them to the client's open order is two clicks from either end and the order reflects it immediately. 5.6 JOB ORDER SELF UPDATES 1. Filling the last seat, inside the placement transaction: requisition status to filled, remaining active applications to filled_by_another with notifications, publish state to unpublished with the sitemap entry dropped by the sweep, audited with cause placement_final. 2. Fall off: a placement ending before its scheduled end frees the seat, flips filled to open with cause fall_off, alerts the order owner and the capture owner where linked, leaves the page unpublished pending human republish. filled_by_another candidates on that order can be reactivated to their prior stage manually, one click, audited. 3. on_hold pauses publishing and SLA timers without disturbing the pipeline. closed is terminal, requires a reason, moves active applications to out with reason order_closed. 5.7 GATE 5 ADDITIONS, CANDIDATES AND DATAFLOW 1. The Candidates page finds a planted candidate by skills filter and by free text through the fusion query, and the missionMATCH command center Candidates screen still renders from shared components with zero regression. 2. Reverse match on a fixture candidate returns an identical ranking across repeated runs, and the engine diff against the starting commit remains empty. 3. Add to job order from the match list creates the application with the score snapshot and added_from match. Eight racing adds of the same pair produce exactly one application. A duplicate add through the API is rejected. 4. Stage counts on the requisition update as the application moves through prescreen, internal submittal, client submittal, interview, and offer, and each tile clicks through correctly. 5. Placing the final seat flips the order to filled, moves remaining fixture applications to filled_by_another with alerts recorded, and the fg-talent.com detail page and sitemap entry are gone. 6. A simulated fall off frees the seat, reopens the order with an alert, does not republish, and a one click reactivation restores a filled_by_another candidate to their prior stage, audited. 7. Re adding a previously rejected candidate demands a reopen reason and records it. 8. A candidate on a proposal slate and in a desk pipeline resolves to one candidate id everywhere. 5.8 ACCEPTANCE ADDITIONS 33. Exactly one active application exists per candidate per requisition, enforced by the database, proven by the race. 34. Every job order status transition, automatic or manual, carries an audited cause, and filled_by_another is distinguishable from rejection in every report. 35. Reverse match rankings are bit reproducible, persisted with engine version, and the frozen engine remains untouched. -------------------------------------------------------------------------------- FINAL MERGE INDEX, VERIFY AFTER APPLYING -------------------------------------------------------------------------------- 1. Directive Section 0 gained the Amendment 1 environment rule. 2. Phase 3 gained the slate approval lifecycle. Gate 3 gained its additions. 3. Phase 5 gained: desk integration A through C, publishing to the tenant website, desk workflow additions 1 through 11, the Import Center and screenMATCH uploads, the Candidates page, reverse match, add to job order, and job order self updates. Gate 5 gained sections 2.8, 4.6, and 5.7. 4. The directive gained the canonical dataflow as a permanent appendix. 5. Section 11 gained acceptance items 25 through 35. 6. Task T1 is registered as standalone work. 7. The fast follow list gained the 2.7 items. Record "consolidation merged and verified" in BUILD_STATE when all seven lines above are true in the working plan.