Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / BUILD_REPORT.md |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 5d5ddff70393a197c5f54a45280bb5dd42b24755 |
| Branch | ai-intelligence-layer |
| Path or archive member | BUILD_REPORT.md |
| Original SHA-256 | 8b632b1141e2f38375f8122c4e37f8ef2c08fe1bbabb6d24d32feac14bc78244 |
| Git blob SHA | 484fbaf0991da856872c3949d6a401ec4750fa27 |
| Reading-copy SHA-256 | 8b632b1141e2f38375f8122c4e37f8ef2c08fe1bbabb6d24d32feac14bc78244 |
Recovered source transcript
Download complete source text ↓165 lines · 11.9 KB
# BUILD_REPORT.md — missionMATCH AI Intelligence Layer
**Date:** 2026-06-26. **Branch:** `ai-intelligence-layer` (off `master`). **Build host:** M2.
**Inference host:** M4 (Apple M4, Metal). **Database:** PostgreSQL 16.14 on M4 (goose v17).
This documents what was built, what was researched and relied on, the test results, what was fixed in
the final scan, and what remains. Status of each capability is one of **LIVE** (built, configured,
tested on real data), **WIRED** (built and tested, not yet exposed as an HTTP route), **SCAFFOLD**
(interface present, fuller build sequenced), or **NEEDS DATA** (waits on labels/history).
## Non-negotiable constraints — all held
1. **No Python in the repo.** Verified: `find . -name '*.py'` outside node_modules is empty. The ML runs
out of process (Ollama on M4). The gateway, client, and tools are pure Go.
2. **FIPS intact.** The API binary builds `CGO_ENABLED=0 GOFIPS140=v1.0.0`; the stamp was verified after
every build (`GOFIPS140=v1.0.0` present). No cgo in any of the four binaries. The circuit breaker is
in house specifically to avoid a third party dependency disturbing the FIPS build.
3. **EEO isolation absolute.** No AI path may name the eeo schema. `internal/modules/ai/safety.go`
(`ForbidEEO`) refuses it at runtime; `TestNoAIFileReferencesEEO` walks every AI source file and fails
if any executable line references it. The TAG allowlist contains no eeo table; sqlc still models no
eeo table. Memory and adjacency are eeo guarded.
4. **Tenant isolation is database per tenant.** `cmd/provision-tenant` creates a complete isolated
database; Postgres itself refuses cross database reads (`TestCrossTenantDatabaseIsolation`). MEGAMIND
is stateless and the teach boundary refuses any client fact (`TestMegamindTeachBoundaryLive`).
5. **The deterministic engine is the floor.** The AI layer reads engine outputs and tenant data and
narrates; it never recomputes a score. Learned ranking (LTR with SHAP and calibration) is scoped to
the reranker on top of the engine and is sequenced (see Remaining).
6. **Every AI action audits.** The orchestrator writes an append only `aedt.ai.answered` /
`aedt.ai.refused` event (route and verdict only, no PII); the backfill writes `aedt.embedding.backfill`.
## Research (primary sources)
An 8 agent research workflow ran against primary sources before building; the full brief is
`docs/AI_RESEARCH.md`. Key decisions taken from it and cited in code:
- **Hybrid RAG in Postgres** (pgvector cosine + tsvector full text fused with Reciprocal Rank Fusion),
with pgvector 0.8 `hnsw.ef_search` and `hnsw.iterative_scan = relaxed_order` set per statement.
- **Adaptive routing**: aggregation questions go to **TAG** (the database computes), not vector RAG.
- **CRAG style self correction over Self-RAG**: a faithfulness gate that needs no fine tuned model, which
fits a stateless commodity inference plane.
- **Structured tool use over free form NL2SQL** for cleared data: the TAG layer selects from a curated
intent registry; the model never authors SQL.
- **384 dim embeddings** (all-minilm now, bge-small-en-v1.5 the documented production target, both 384)
to match the existing `vector(384)` columns with no migration.
## What was built, by phase
### Phase 0 — MEGAMIND inference plane, client, scrub boundary — LIVE
- `cmd/megamind-gateway` (pure Go, stateless): `/v1/embed`, `/v1/rerank`, `/v1/generate`,
`/v1/faithfulness`, `/v1/teach`, `/healthz`. Proxies Ollama (embeddings all-minilm 384, generation
llama3.1:8b), wraps generation with a prompt injection guard, persists nothing. **Deployed and running
on M4** (Tailscale only bind `100.94.8.94:8090`). Smoke tested: embed 384, rerank cosine, faithfulness
via llama3.1, teach refuses a client fact (422).
- `internal/platform/inference`: typed client (Embed, Rerank, Generate, CheckFaithfulness, Teach,
Health) with per request timeout, bounded retries, and an in house circuit breaker. Embed hard fails
on a width other than 384.
- `internal/platform/scrub`: the teaching boundary. `TeachingSignal` is a closed abstract struct;
`Validate` refuses any UUID, email, out of vocabulary value, free text run, or stray field, enforced on
both the tenant side and the gateway.
- Tests: scrub boundary (unit), breaker and client (unit), live reachability and 384 dim and teach
boundary (integration on M4).
### Phase 1 — per tenant vector and isolation, vectors made live — LIVE
- `cmd/provision-tenant`: creates a schema identical, isolated tenant database (embedded migrations +
goose). Proven on M4: 17 public + 1 eeo migration, RLS forced, app role has zero grant on
`eeo.candidate_demographics`, pgvector ready.
- `cmd/embed-backfill`: embeds candidates and skills through the plane into the `vector(384)` columns.
**Run on M4**: `skills.embedding` 0 to 61, demo `candidates.resume_embedding` to 1511. The HNSW indexes
and `SearchSkillsByEmbedding` are now live (AWS nearest neighbors are Cybersecurity, Splunk, Systems
Engineering). The skill matcher runs on real cosine (the `megamind` embedding provider).
- Tests: cross tenant database isolation, erasure wipes the resume vector, the embedder uses real
semantics (a synonym matches with the plane, not with the fake hash).
### Phases 2-7 — augmented generation module (`internal/modules/ai`)
- **Safety (`safety.go`) — LIVE**: `ForbidEEO`, `GuardReadOnlyQuery` (single SELECT, no stacked
statements, no hidden CTE writes, allowlisted tables only), `ReadAllowlist`. The required EEO tripwire
test passes.
- **TAG (`tag.go`) — WIRED**: a curated registry of named, parameterized, read only intents (no eeo),
each validated at startup and execution, run RLS scoped. Tested live (`count_candidates_by_clearance`).
The model selects and parameterizes; it never authors SQL.
- **RAG retrieval (`retrieval.go`) — WIRED**: hybrid pgvector + tsvector + RRF over the live vectors,
RLS scoped, pgvector 0.8 tuned, eeo guarded.
- **Orchestrator (`orchestrator.go`) — WIRED**: the adaptive router (aggregation to TAG, retrieval to
RAG, else direct), the faithfulness gate (an unconfirmed answer is withheld and routed for human
review), and the AEDT audit on every action.
- **Extraction (Phase 2)**: the deterministic server side extractor already exists (resume to fields).
A plane backed, layout aware extractor (LayoutLMv3/Donut or a local VLM) and a Section L and M parser
are **SCAFFOLD/NEEDS DATA**: they require a model served out of process and labeled solicitations; the
extraction port is config switchable for that backend.
- **Reranker (Phase 3)**: the `/v1/rerank` endpoint is live as a cosine baseline; the bge-reranker-v2-m3
cross encoder is the documented upgrade. Boolean query generation for sourcing is **SCAFFOLD**.
### Phase 4 — scoring reconciliation
Reconciliation by routing, the safe choice that does not change the working Command Center: **the AI/TAG
layer reads the deterministic engine's persisted outputs (`candidate_evaluations`, `slate_members`),
never the separate Command Center SQL composite.** So the brain's org level answers are the engine's own
numbers and cannot contradict it. The two implementations still co exist for their different purposes
(per candidate engine vs org level dashboard aggregate); merging the Command Center composite into the
engine is a larger refactor recommended in Remaining.
### Phase 5 — KAG and GraphRAG
- **KAG skill adjacency (`scaffolds.go`) — LIVE**: `SkillAdjacency` over the now populated
`skills.embedding` HNSW (the substitution reasoner the audit found missing). Clearance reciprocity
already lives in the engine.
- **GraphRAG teaming graph — SCAFFOLD**: the node/edge model over awards and opportunity_records is
designed; the raw relationships exist; the extraction and community summarization pass is sequenced.
### Phase 6 — CAG — LIVE
`PublicRules()` preloads the fixed weights, bands, clearance hierarchy and reciprocity, and the standing
disclaimers into model context (contents free, fits easily), so the model never retrieves or invents them.
### Phase 7 — agentic and self correction — WIRED
The router + faithfulness gate + guardrails + AEDT audit (above). Multi step planning (slate assembly as
a plan) is **SCAFFOLD** on top of the router.
### Phase 8 — per tenant memory and learning — WIRED / SCAFFOLD
- **Memory (`memory.go`, migration 0017) — WIRED**: per tenant episodic and semantic memory inside the
tenant database (RLS, vector(384), HNSW), candidate scoped. `ForgetCandidate` wipes it, and the right
to erasure path (`sourcing.Delete`) now deletes a candidate's memory. Tested live (store, recall,
erase).
- **Active learning + LTR reranker with SHAP and calibration — SCAFFOLD/NEEDS DATA**: the labels exist
(`slate_members.decision`, `candidate_evaluations`); the learned reranker that sits on top of the
engine (the only place SHAP and calibration belong) is sequenced.
- **Federated learning + differential privacy — DESIGNED, DISABLED**: `FederatedLearningEnabled = false`;
`DefaultFederatedConfig` fixes the privacy budget and the minimum tenant count. Transmission is off and
the scrub boundary withholds it.
### Phase 9 — capture and foresight — SCAFFOLD / NEEDS DATA
Win probability, bid or no bid, price to win (from BLS and USASpending), clearance survival analysis, and
demand forecasting are interface fixed and marked needs data (they need a labeled win/loss and clearance
timing history the platform does not have enough of yet).
## Test results
- Unit (race + fips): **all pass**, including the engine frozen and golden tests, the scrub boundary, the
inference breaker and client, and the AI safety and EEO tripwire.
- Live integration on M4: **39 pass, 0 fail** (the original 31 plus 8 new: megamind reachability and
teach boundary, cross tenant database isolation, erasure wipes vector, real semantics, AI memory
erasure, KAG adjacency, TAG intent).
- `go vet`, `staticcheck`, `oxlint`: clean. `make ci-gates`: backdoor and FIPS gates pass. Frontend
build: clean.
## What was fixed in the final scan
- Removed the four dead env keys the audit flagged (`DATA_GOV_API_KEY`, `KAGGLE_USERNAME`, `KAGGLE_KEY`,
`HF_TOKEN`) from `.env.example`; documented the AI plane variables. The host env cleanup is in
DEPLOY_PLAN.md.
- Added `compliance.write` and re gated the governance writes (register an AEDT tool, run retention) on
it instead of the read capability (the audit's authz granularity flag).
- Regenerated sqlc so `ai_memory` is modeled.
## What remains (genuine human decisions or sequenced work)
1. **Activate the AI HTTP surface.** The orchestrator, TAG, RAG, and memory are WIRED and tested as a
library but not yet exposed as authenticated chi routes; that is a small wiring step deferred to the
cutover so the live demo is not disturbed.
2. **Database per tenant routing in the API.** The provisioning primitive and isolation are built and
proven; switching the running API from the shared single database to per tenant pools is the migration
the cutover performs (the current shared+RLS model still works in the interim).
3. **Per tenant role hardening.** Today tenant databases share the cluster roles; physical isolation
holds (Postgres refuses cross database reads), but per tenant credentials would prevent a compromised
credential from reaching another tenant database by switching the database name. Recommended.
4. **bge-small-en-v1.5 and bge-reranker-v2-m3.** all-minilm (384) is live; swapping to bge-small (also
384, no migration) and serving the cross encoder reranker improves quality. A config change plus a
one time re backfill.
5. **Scoring reconciliation as a code merge.** The AI layer is reconciled by routing to engine outputs;
merging the Command Center SQL composite into the engine would remove the second gating path entirely.
6. **Phase 2 layout aware extraction, Phase 9 foresight, GraphRAG, LTR reranker, federated loop.**
Sequenced as above; they need a served extraction/rerank model, labeled history, or multiple live
clients.