ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / DEPLOY_PLAN.md

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / DEPLOY_PLAN.md
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberDEPLOY_PLAN.md
Original SHA-256f6e870f400a48efcbe2aaa6e22665d5d7ec399bb0d33da7ee1563f867048ef3c
Git blob SHA33eb6fe1d6c7d30651433e168c1d55e95c75b6ca
Reading-copy SHA-256f6e870f400a48efcbe2aaa6e22665d5d7ec399bb0d33da7ee1563f867048ef3c

Original source ↗

Every recorded occurrence

These 23 records contain identical original source bytes. Their paths and revisions remain part of the archive.

Original recordBranch or archiveRevision / identifierOriginal location
Janady13/missionmatch / DEPLOY_PLAN.mdfeature/opportunity-to-outcome720d47fae476b0d38477ae4401697d372b1ea2bcOpen original
Janady13/missionmatch / DEPLOY_PLAN.mdper-tenant-routing9bde0f9a74b89d01980fa658e5253acda7528d0cOpen original
Janady13/missionmatch / DEPLOY_PLAN.mdcollision-deconfliction4ee5a09972608ed89f8377c6665542d5f450f0a6Open original
Janady13/missionmatch / DEPLOY_PLAN.mdws6-retrieval6c56e29231ec05735927fa265c97d517499dfeafOpen original
Janady13/missionmatch / DEPLOY_PLAN.mdm5-price-to-win41000ad30fff4129fdaf5ec84e15ba14c27d4890Open original
Janady13/missionmatch / DEPLOY_PLAN.mdws1-ontology-syncb596f449a32a1016fbd403c36505cc00a1ac9ee6Open original
Janady13/missionmatch / DEPLOY_PLAN.mdmaster1e9249840a4302ec82e123b9c9cb6f75badea3e4Open original
Janady13/missionmatch / DEPLOY_PLAN.mdws8-teaching-loopc823f0fb6bb2aba0f39001eb6de96f4000d9321fOpen original
Janady13/missionmatch / DEPLOY_PLAN.mdmag-substrateb82c7100a492dec67dfd1eda6b3f53def859be35Open original
Janady13/missionmatch / DEPLOY_PLAN.mdws3-clearance4b8e7ce594c068621867f9c9deed0ec64ae6c553Open original
Janady13/missionmatch / DEPLOY_PLAN.mdphase2-eval-fairnessd361af254701975fe239927656ababb56374655eOpen original
Janady13/missionmatch / DEPLOY_PLAN.mdtime-to-fill-survivalb66e1e505863d4f17741a4b9ede73509e45bd6c6Open original
Janady13/missionmatch / DEPLOY_PLAN.mdgraphrag-foundationb0ddeb9f633fd138d09309d1a17b7d13bc3a67f7Open original
Janady13/missionmatch / DEPLOY_PLAN.mddeploy-and-opsbdacd9d0b4d5998d25fc74bf4007f4c3ec538c7aOpen original
Janady13/missionmatch / DEPLOY_PLAN.mdws9-bench-ingestionf585a9ef32fa554663ce1fba9a414a54b6e49cf0Open original
Janady13/missionmatch / DEPLOY_PLAN.mdws2-alias-relationshipe4dada4601c6eb101830f9d223a9655dfa120616Open original
Janady13/missionmatch / DEPLOY_PLAN.mdpresentation-readinesseb574acaa29d71ce4d0f852572e87c275c79fdb7Open original
Janady13/missionmatch / DEPLOY_PLAN.mdvendor-intelligencefe9796a19c261951d3f2565206c0c1b5ac294465Open original
Janady13/missionmatch / DEPLOY_PLAN.mdws7-federal-signal6a9f6ce9cfb13345ffb47770d4960e7c2d9c17c2Open original
Janady13/missionmatch / DEPLOY_PLAN.mdai-brain-liveaac32fc49c878cc5bca099459307611562d0bac1Open original
Janady13/missionmatch / DEPLOY_PLAN.mdphase2-connectorse038d4c687aec16f8bd9bc4d907eea14d91f8704Open original
Janady13/missionmatch / DEPLOY_PLAN.mdfeature/aioe-upgrade2178e7298d0e5d9af83afa12402fd587f0ba6ed8Open original
Janady13/missionmatch / DEPLOY_PLAN.mdcapture-readinessbae6af7cb2997e819174a9e9cfff5e16067a1975Open original

Recovered source transcript

# DEPLOY_PLAN.md — AI Intelligence Layer cutover The build is validated in a staging posture. This is the exact, ordered, rollback ready plan for the **human** to run the irreversible live cutover. It is the one manual step: Bubbles serves other live paying client sites and this build provisions cleared data databases. **Do not run the Bubbles steps automatically.** Everything below was dry run and validated; the operator executes the Bubbles and live database steps. ## State at handoff (already done, staging) - The MEGAMIND gateway is **running on M4** (`100.94.8.94:8090`, Tailscale only, via `nohup`) and smoke tested. Ollama on M4 has `all-minilm` (384) and `llama3.1:8b`. - The shared production database on M4 is at **goose v17**; `0017_ai_memory.sql` is applied (additive, a new table the old API binary does not use, so it is safe alongside the running old binary). - `skills.embedding` (61/61) and the demo org `candidates.resume_embedding` (1511/1511) are backfilled. - A staging tenant database `tenant_staging_demo` was provisioned on M4 to validate `provision-tenant`. - The Bubbles `mm-api` service is **unchanged** (still the pre AI binary). ## Merge sequence (do this FIRST, before any cutover step below) The stack is three branches: the brain sits on W3, which sits on the AI intelligence layer. Merge them in this order, as three DISCRETE steps, each merged and validated and individually rollback able, because each carries its own migration and is a separate revertable unit. Do NOT collapse them into one merge. **Step M1 - merge the AI intelligence layer branch first (the foundation; carries migration 0017, ai_memory).** It is the base of the stack and the only branch the others depend on. Validate (build FIPS, unit suite, integration on a staging database) before proceeding. Rollback: revert the merge commit. If 0017 was already applied to a database, `goose down` one step (the 0017 down drops ai_memory), per the rollback in `db/migrations/0017_ai_memory.sql`. **Step M2 - then merge W3 (carries migration 0018, recommendation_runs and staffing_recommendations).** Only after M1 is merged and green. Validate again. Rollback: revert the W3 merge commit. If 0018 was applied, `goose down` to v17 (the 0018 down DROPs the two W3 tables), per the rollback referenced in Step W3.1. **Step M3 - then merge the brain (carries migration 0019, the v1.1.0 model version registry row).** Only after M2 is merged and green. The brain adds NO new schema table; 0019 inserts one row into aedt_model_versions registering the recalibrated semantic threshold (v1.1.0), which the engine now stamps onto every decision. Validate again. Rollback: revert the brain merge commit. If 0019 was applied, `goose down` to v18 (the 0019 down DELETEs the v1.1.0 registry row), per the rollback in `db/migrations/0019_model_version_v1_1_0.sql`. Note that reverting the brain code without reverting 0019 is safe (a registry row with no stamping engine is inert), and reverting to a binary that stamps v1.0.0 with the v1.1.0 row present is also safe. **Hard rule.** Do not collapse these into one merge, and do NOT run the production cutover sequence below until all three branches are merged in this M1, M2, M3 order AND the migrations through 0019 are applied to the production shared database. The cutover steps assume a single merged tree at migration head v19. ## Build the artifacts (on the build host, no live mutation) ``` cd ~/missionmatch && git checkout ai-intelligence-layer # API (Bubbles target), FIPS, verify the stamp: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOFIPS140=v1.0.0 go build -trimpath -o /tmp/mm-api ./cmd/api go version -m /tmp/mm-api | grep GOFIPS140 # must show GOFIPS140=v1.0.0 # Gateway + tools (M4 target): CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o /tmp/megamind-gateway ./cmd/megamind-gateway CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o /tmp/provision-tenant ./cmd/provision-tenant CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o /tmp/embed-backfill ./cmd/embed-backfill # Frontend (unchanged this cutover; rebuild only if you changed it): cd frontend && npm run build ``` ## Step 1 — durable MEGAMIND gateway on M4 (launchd) Replaces the staging `nohup` with a managed service. ``` scp /tmp/megamind-gateway joseph@100.94.8.94:/tmp/megamind-gateway scp infra/launchd/com.missionmatch.megamind-gateway.plist joseph@100.94.8.94:/tmp/ ssh joseph@100.94.8.94 ' pkill -f /tmp/megamind-gateway || true # stop the staging nohup instance sudo cp /tmp/megamind-gateway /usr/local/bin/megamind-gateway && chmod +x /usr/local/bin/megamind-gateway cp /tmp/com.missionmatch.megamind-gateway.plist ~/Library/LaunchAgents/ launchctl unload ~/Library/LaunchAgents/com.missionmatch.megamind-gateway.plist 2>/dev/null || true launchctl load ~/Library/LaunchAgents/com.missionmatch.megamind-gateway.plist ' # Verify: curl -s http://100.94.8.94:8090/healthz # -> ok curl -s http://100.94.8.94:8090/v1/embed -d '{"inputs":["x"]}' | jq .dimension # -> 384 ``` Rollback: `ssh joseph@100.94.8.94 'launchctl unload ~/Library/LaunchAgents/com.missionmatch.megamind-gateway.plist'`. Optional quality upgrade (no migration, both 384): pull bge-small and set `MEGAMIND_EMBED_MODEL`: `ssh joseph@100.94.8.94 'ollama pull <bge-small-en-v1.5-gguf>'` then re run the backfill (Step 4). ## Step 2 — env on Bubbles (operator; root owned 0600 files) Add the AI plane variables to `/etc/missionmatch/api.env` (back it up first): ``` sudo cp /etc/missionmatch/api.env /etc/missionmatch/api.env.bak.$(date +%s) # append (do not echo secrets to a log): MM_EMBED_PROVIDER=megamind MM_MEGAMIND_URL=http://100.94.8.94:8090 MM_EMBED_DIMENSION=384 MM_MEGAMIND_EMBED_MODEL=all-minilm MM_MEGAMIND_GENERATE_MODEL=llama3.1:8b MM_MEGAMIND_TEACHING_ENABLED=false ``` Remove the dead keys from `/etc/missionmatch/sam-sync.env` (back it up first): `DATA_GOV_API_KEY`, `KAGGLE_USERNAME`, `KAGGLE_KEY`, `HF_TOKEN`. Rollback: restore the `.bak` files. ## Step 3 — database (already at v17; only new tenants need provisioning) The shared database is at v17. If you maintain it, confirm: ``` ssh joseph@100.94.8.94 'PGURL=... goose -dir db/migrations postgres "$PGURL" status' # 0017 applied ``` For a NEW client (database per tenant), provision a fresh database (this is the irreversible "create a live client database" step; run only for a real onboarding): ``` ssh joseph@100.94.8.94 '/usr/local/bin/provision-tenant \ -admin-dsn "host=/tmp user=postgres dbname=postgres sslmode=disable" \ -name tenant_<client_slug>' ``` It applies the full public + eeo migration set, RLS forced, eeo segregated, vector(384) ready, and verifies the app role has no grant on `eeo.candidate_demographics`. Rollback (only if the database is brand new and unused): `DROP DATABASE tenant_<client_slug>`. ## Step 4 — embed backfill (idempotent) For the shared database (the demo org is already done) or a freshly provisioned tenant database, once it has candidates: ``` ssh joseph@100.94.8.94 '/usr/local/bin/embed-backfill \ -dsn "postgres://missionmatch_migrator:<pw>@127.0.0.1:5432/<db>?sslmode=disable" \ -megamind http://100.94.8.94:8090 -what all -only-missing -batch 64' ``` `-only-missing` makes it safe to re run. Rollback: `UPDATE skills SET embedding=NULL; UPDATE candidates SET resume_embedding=NULL;` then re run (or leave; embeddings are additive). ## Step 5 — THE CUTOVER on Bubbles (operator, irreversible; brief downtime) Swap the mm-api binary to the AI build and restart. Back up the current binary first. ``` scp /tmp/mm-api user@bubbles:/tmp/mm-api.new ssh user@bubbles ' sudo cp /home/user/missionmatch/mm-api /home/user/mm-api.bak.$(date +%s) # backup sudo systemctl stop mm-api sudo cp /tmp/mm-api.new /home/user/missionmatch/mm-api && sudo chmod +x /home/user/missionmatch/mm-api sudo systemctl start mm-api sleep 2 && systemctl is-active mm-api ' # Verify the live API still answers and FIPS is on: curl -s https://missionmatch.thatwebhostingguy.com/healthz # -> ok curl -s https://missionmatch.thatwebhostingguy.com/healthz/fips | jq .fips_enabled # -> true ``` **Rollback (fast):** ``` ssh user@bubbles ' sudo systemctl stop mm-api sudo cp /home/user/mm-api.bak.<ts> /home/user/missionmatch/mm-api sudo systemctl start mm-api ' # and restore /etc/missionmatch/api.env.bak.<ts> if the env changes caused the issue. ``` Nginx is **unchanged** by this cutover (the gateway is reached over Tailscale, not through nginx). No `nginx -t` or reload is required. The systemd unit `mm-api.service` is unchanged; only the binary and the env file change. ## Step 6 — host service hygiene (operator) The audit found the `mm-sam-sync.timer` showed no next elapse. The unit is valid (`OnCalendar=*-*-* 04:00:00`); ensure it is started: ``` ssh user@bubbles 'sudo systemctl daemon-reload && sudo systemctl enable --now mm-sam-sync.timer && systemctl list-timers | grep mm-sam-sync' ``` ## Activating the AI HTTP surface (a later, separate change) The orchestrator, TAG, RAG, and memory are built and tested as a library but are not yet mounted as authenticated routes (deferred so this cutover does not change the user facing app). Mounting them is a small code change behind the session resolver, RBAC, and the same audit, then a repeat of Step 5. ## Post cutover checks - `curl https://missionmatch.thatwebhostingguy.com/healthz/fips` shows `fips_enabled: true`. - The MEGAMIND gateway `launchctl list | grep megamind` is running on M4. - `make ci-gates` on the build host stays green (backdoor + FIPS). - No EEO reach: `go test ./internal/modules/ai/...` (the tripwire) stays green in CI. ## W3 AI Staffing Recommendations cutover (additive, on top of the AI layer) W3 is a backend addition: migration 0018, four new authenticated routes already mounted in the mm-api binary, and one new scheduled job. It is additive and reversible. As with the AI layer, the operator runs the Bubbles and production database steps; everything below was built and validated on M4 staging (migration 0018 applies cleanly through v18 plus eeo, and 5 of 5 W3 integration tests pass). ### State at handoff (already done, staging) - Migration 0018 (recommendation_runs, staffing_recommendations) is written and proven on a fresh M4 staging database `tenant_w3_staging` (goose v18). It is NOT applied to the production shared database. - The mm-api binary on the build host now carries the four W3 routes (staffing.recommend gated), but the Bubbles mm-api is unchanged (still the pre AI binary), so nothing is live yet. - The new `staffing-proactive-sync` binary and `mm-staffing-proactive.{service,timer}` are written but NOT installed on Bubbles. ### Build the artifacts (build host, no live mutation) ``` cd ~/missionmatch && git checkout w3-ai-staffing-recommendations CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOFIPS140=v1.0.0 go build -trimpath -o /tmp/mm-api ./cmd/api go version -m /tmp/mm-api | grep GOFIPS140 # must show GOFIPS140=v1.0.0 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOFIPS140=v1.0.0 go build -trimpath -o /tmp/staffing-proactive-sync ./cmd/staffing-proactive-sync ``` ### Step W3.1 - apply migration 0018 to the production shared database (operator, irreversible) This is the one irreversible step. 0018 only ADDS two tables and is safe alongside the running old binary (the old binary does not use them). Run as the migrator role. ``` ssh joseph@100.94.8.94 'cd ~/missionmatch && \ goose -dir db/migrations postgres "postgres://missionmatch_migrator:<pw>@127.0.0.1:5432/missionmatch?sslmode=disable" up' # verify: goose ... status shows 0018 applied, head v18 ``` Rollback (only before any recommendation rows matter): `goose ... down` once, or `DROP TABLE staffing_recommendations; DROP TABLE recommendation_runs;`. ### Step W3.2 - deploy the mm-api binary that carries the W3 routes (operator, brief downtime) Same binary swap as the AI layer Step 5; this build also mounts the four W3 routes behind staffing.recommend / slate.write / candidate.read. Back up the current binary first. ``` scp /tmp/mm-api user@bubbles:/tmp/mm-api.new ssh user@bubbles ' sudo cp /home/user/missionmatch/mm-api /home/user/mm-api.bak.$(date +%s) sudo systemctl stop mm-api sudo cp /tmp/mm-api.new /home/user/missionmatch/mm-api && sudo chmod +x /home/user/missionmatch/mm-api sudo systemctl start mm-api sleep 2 && systemctl is-active mm-api ' curl -s https://missionmatch.thatwebhostingguy.com/healthz/fips | jq .fips_enabled # -> true ``` Rollback: stop mm-api, restore `/home/user/mm-api.bak.<ts>`, start mm-api. ### Step W3.3 - install the proactive recompute timer (operator) ``` scp /tmp/staffing-proactive-sync user@bubbles:/home/user/missionmatch/staffing-proactive-sync ssh user@bubbles ' sudo cp infra/systemd/mm-staffing-proactive.* /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now mm-staffing-proactive.timer systemctl start mm-staffing-proactive.service # one off, to seed the first bench watch systemctl list-timers | grep mm-staffing-proactive ' ``` Rollback: `sudo systemctl disable --now mm-staffing-proactive.timer`. The watch freshness depends on the ingestion timers (mm-sam-sync, mm-opp-sync); the proactive timer is scheduled after them at 05:00. ### Post cutover checks (W3) - `curl -sf -X POST https://missionmatch.thatwebhostingguy.com/api/missionmatch/recommendations/portfolio` with a valid session returns a 200 allocation (or 403 without staffing.recommend); an unauthenticated call is 403. - A staffing run writes one `aedt.staffing.recommended` audit and a decision writes one `aedt.staffing.decided`. - `go test -tags=integration -run TestStaffing ./internal/integration/` stays green against the database. - The EEO tripwire `go test ./internal/modules/ai/...` stays green (it now walks the staffing package too). ### Note: feed freshness The proactive bench watch only surfaces an opportunity once the ingestion timers (mm-sam-sync, mm-opp-sync) have ingested it. The audit previously flagged the SAM sync timer as possibly not firing; confirm `systemctl list-timers | grep mm-sam-sync` shows a next elapse before relying on the watch for new postings. ## AI brain activation cutover (mount the brain live, additive) This activates the brain on the SHARED RLS database that runs today (per tenant pools are a sequenced follow on, out of scope). It mounts one new route (POST /ai/query), switches the live embedder to bge-small-en-v1.5, and re embeds the vectors. Validated end to end on M4 staging (the brain_staging database, 46 of 48 integration pass, 1 environmental fail unrelated to the brain, 4 of 4 brain tests pass). Nothing below was run against production. ### Dependency (must be true first) - All three branches are merged in the M1, M2, M3 order above, and the migrations through 0019 are applied to the production shared database (ai_memory is 0017 from the AI layer, the W3 tables are 0018, and the v1.1.0 model version registry row is 0019 from the brain branch, added by the threshold recalibration). The brain branch sits on top of both and carries only that one registry row migration, no new table. - Apply 0019 to production if it is not yet at v19 (additive, a single registry row, safe alongside the running binary): ``` ssh joseph@100.94.8.94 'PGURL="postgres://missionmatch_migrator:<pw>@127.0.0.1:5432/missionmatch?sslmode=disable"; goose -dir db/migrations postgres "$PGURL" up' ssh joseph@100.94.8.94 'PGURL=...; goose -dir db/migrations postgres "$PGURL" status' # head v19, 0019 applied ``` Rollback: `goose -dir db/migrations postgres "$PGURL" down` to v18 (DELETEs the v1.1.0 registry row). - bge-small-en-v1.5 is available on the production Ollama. It is NOT in the official Ollama library; pull the community handle (384 dim, standard /api/embed): ``` ssh joseph@100.94.8.94 'curl -s http://127.0.0.1:11434/api/pull -d "{\"name\":\"qllama/bge-small-en-v1.5\",\"stream\":false}"' # probe: the embedding must be 384 wide ssh joseph@100.94.8.94 'curl -s http://127.0.0.1:11434/api/embed -d "{\"model\":\"qllama/bge-small-en-v1.5\",\"input\":\"x\"}" | head -c 60' ``` ### Step B1 - env on Bubbles (operator, root owned 0600 files; back up first) Append to /etc/missionmatch/api.env: ``` MM_EMBED_PROVIDER=megamind MM_MEGAMIND_URL=http://100.94.8.94:8090 MM_EMBED_DIMENSION=384 MM_MEGAMIND_EMBED_MODEL=qllama/bge-small-en-v1.5 MM_MEGAMIND_GENERATE_MODEL=llama3.1:8b ``` Set the same MM_MEGAMIND_EMBED_MODEL in the sync env used by embed-backfill, and update the M4 gateway launchd env MEGAMIND_EMBED_MODEL to qllama/bge-small-en-v1.5 (the rerank path uses the gateway default). Rollback: restore the .bak files. ### Step B2 - re backfill the production vectors with bge (operator, irreversible to the prior vectors) CRITICAL: production currently holds all-minilm vectors (from the AI layer). bge and all-minilm vectors are NOT comparable, so the query (bge) versus stored (all-minilm) mismatch would silently corrupt retrieval. Re embed EVERYTHING with bge BEFORE serving the brain. NULL the columns first so a row that errors mid run is left unembedded (a safe no semantic match) rather than retaining a stale all-minilm vector, then run a FULL re embed (no -only-missing, so every row is rewritten with bge): ``` ssh joseph@100.94.8.94 'psql -U postgres -d missionmatch -c "UPDATE candidates SET resume_embedding=NULL; UPDATE skills SET embedding=NULL"' ssh joseph@100.94.8.94 '/usr/local/bin/embed-backfill \ -dsn "postgres://missionmatch_migrator:<pw>@127.0.0.1:5432/missionmatch?sslmode=disable" \ -megamind http://100.94.8.94:8090 -model qllama/bge-small-en-v1.5 -what all -batch 64' ``` THE RE EMBED GATE (enforced, not a glance). The verify below is a hard ASSERTION: it RAISES (non zero exit under ON_ERROR_STOP) unless every embedding is present and 384 wide. Do NOT proceed to B3 unless this assertion passes. The brain routes stay dark until the bge backfill is verified complete. Deleted and anonymized candidates legitimately keep a NULL resume_embedding (the right to erasure), so the candidate assertion scopes to live rows, exactly the set the backfill targets; skills must be embedded in full. ``` ssh joseph@100.94.8.94 'psql -U postgres -d missionmatch -v ON_ERROR_STOP=1 <<SQL DO \$\$ DECLARE s_total int; s_emb int; c_total int; c_emb int; w int; BEGIN SELECT count(*), count(embedding) INTO s_total, s_emb FROM skills; SELECT count(*), count(resume_embedding) INTO c_total, c_emb FROM candidates WHERE deleted_at IS NULL AND anonymized_at IS NULL; SELECT vector_dims(embedding) INTO w FROM skills WHERE embedding IS NOT NULL LIMIT 1; IF s_emb <> s_total THEN RAISE EXCEPTION ''skills not fully embedded: %% of %%'', s_emb, s_total; END IF; IF c_emb <> c_total THEN RAISE EXCEPTION ''live candidates not fully embedded: %% of %%'', c_emb, c_total; END IF; IF w IS DISTINCT FROM 384 THEN RAISE EXCEPTION ''sampled vector width %% not 384'', w; END IF; RAISE NOTICE ''BACKFILL VERIFIED: skills %%/%%, live candidates %%/%%, width %%'', s_emb, s_total, c_emb, c_total, w; END \$\$; SQL' ``` Rollback: the prior all-minilm vectors are not retained; if rolling back, leave bge vectors in place (the prior binary re embeds skill names at request time and ignores the stored column, so it is unaffected). ### Step B3 - deploy the binary that mounts the brain (operator, brief downtime) The new mm-api mounts POST /ai/query (capability brain.query) and uses the stored embedding skill matcher. Back up the current binary first; same swap as the prior cutovers. ``` CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOFIPS140=v1.0.0 go build -trimpath -o /tmp/mm-api ./cmd/api go version -m /tmp/mm-api | grep GOFIPS140 # must show GOFIPS140=v1.0.0 scp /tmp/mm-api user@bubbles:/tmp/mm-api.new ssh user@bubbles ' sudo cp /home/user/missionmatch/mm-api /home/user/mm-api.bak.$(date +%s) sudo systemctl stop mm-api sudo cp /tmp/mm-api.new /home/user/missionmatch/mm-api && sudo chmod +x /home/user/missionmatch/mm-api sudo systemctl start mm-api && sleep 2 && systemctl is-active mm-api ' ``` The skill matcher caches the global skill vectors on first use; the restart in this step picks up the bge backfill. Rollback: stop mm-api, restore /home/user/mm-api.bak.<ts>, start mm-api (the /ai/query route disappears; the older binary is unaffected by the bge vectors). STARTUP VECTOR MODEL CHECK (the binary enforces the gate, belt and suspenders to the B2 assertion). On boot, with a configured plane, the API runs a self check: it asserts the skills.embedding and candidates.resume_embedding columns are vector(384), samples stored skill vectors, and re embeds them with the configured MM_MEGAMIND_EMBED_MODEL to confirm the stored vectors were produced by that model (cosine within tolerance). If the stored vectors do NOT match the configured model (the all-minilm versus bge corruption mode, for example if an operator skipped or half ran B2), POST /ai/query returns a typed 503 vector_model_mismatch and the mismatch is logged, while the rest of the API serves normally; the brain stays dark until the store is re embedded and the binary restarted. A boot time plane outage leaves the check to self heal on the first query after the plane recovers. So /ai/query stays dark until BOTH the B2 re embed is verified complete AND the startup vector model check passes; the brain never serves a query over a mismatched vector store. ### Step B4 - verify the brain answers end to end (operator) ``` # with a valid session + CSRF (capability brain.query): curl -s -X POST https://missionmatch.thatwebhostingguy.com/api/missionmatch/ai/query \ -H 'Content-Type: application/json' -b "$COOKIES" -H "X-CSRF-Token: $CSRF" \ -d '{"question":"who are the top cleared cloud security candidates"}' | jq '{path, rationale_source, citations}' # a demographic question must be refused (422), an aggregation intent must compute from the database: curl -s ... -d '{"intent":"count_candidates_by_clearance","args":[""]}' | jq .answer curl -s -o /dev/null -w "%{http_code}" ... -d '{"question":"list candidates by race"}' # -> 422 curl -s https://missionmatch.thatwebhostingguy.com/healthz/fips | jq .fips_enabled # -> true ``` ### Post cutover checks (brain) - A brain query writes one aedt.ai.answered (or aedt.ai.refused) audit, no PII, no prose. - A plane outage returns a typed 503 (never a hang); a faithfulness fallback returns a 200 with rationale_source deterministic. - `go test -tags=integration -run TestBrain ./internal/integration/` stays green against the database, and the EEO tripwire `go test ./internal/modules/ai/...` stays green (it walks the brain files). - Staging cleanup when done: `DROP DATABASE brain_staging` (and the W3 tenant_w3_staging) on M4.

Search equations, builds, manuscript text, and recovered sources.