Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md |
| Original SHA-256 | d6f7760adfbef0aadbf114b0562dc89998e44f1be93e807d4e0f3fcda1390b19 |
| Git blob SHA | f010c3da003b3b52deabe2f5a000827aa1c47081 |
| Reading-copy SHA-256 | d6f7760adfbef0aadbf114b0562dc89998e44f1be93e807d4e0f3fcda1390b19 |
Every recorded occurrence
These 25 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | per-tenant-routing | 9bde0f9a74b89d01980fa658e5253acda7528d0c | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws6-retrieval | 6c56e29231ec05735927fa265c97d517499dfeaf | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws1-ontology-sync | b596f449a32a1016fbd403c36505cc00a1ac9ee6 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws8-teaching-loop | c823f0fb6bb2aba0f39001eb6de96f4000d9321f | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | w3-ai-staffing-recommendations | 43d56387270ef4da4cabd794d97ca6a49909bc7d | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws3-clearance | 4b8e7ce594c068621867f9c9deed0ec64ae6c553 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | phase2-eval-fairness | d361af254701975fe239927656ababb56374655e | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ai-intelligence-layer | 5d5ddff70393a197c5f54a45280bb5dd42b24755 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | deploy-and-ops | bdacd9d0b4d5998d25fc74bf4007f4c3ec538c7a | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws9-bench-ingestion | f585a9ef32fa554663ce1fba9a414a54b6e49cf0 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws2-alias-relationship | e4dada4601c6eb101830f9d223a9655dfa120616 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | vendor-intelligence | fe9796a19c261951d3f2565206c0c1b5ac294465 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ws7-federal-signal | 6a9f6ce9cfb13345ffb47770d4960e7c2d9c17c2 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | ai-brain-live | aac32fc49c878cc5bca099459307611562d0bac1 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | phase2-connectors | e038d4c687aec16f8bd9bc4d907eea14d91f8704 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
| Janady13/missionmatch / docs/superpowers/specs/2026-06-29-w3-ai-staffing-recommendations-design.md | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
Recovered source transcript
Download complete source text ↓302 lines · 17.5 KB
# W3 AI Staffing Recommendations, design
Date: 2026-06-29. Workstream: W3, on the missionMATCH platform. Builds on W0 (AEDT
compliance foundation), W1 (Mission Check), W2 (Revenue at Risk command center),
slateMATCH (slate generation), and the AI intelligence layer (the `internal/modules/ai`
package and the stateless MEGAMIND inference plane).
## 1. Purpose
slateMATCH already scores and ranks candidates per requirement, and the W2 command center
already names the staffing gaps and their dollar exposure. The missing layer is the one
that turns that scored candidate by requirement matrix into explained, recommended actions
that a human approves or rejects. W3 is that layer.
It serves three views, all of one recommendation core:
1. Close the named gaps. For each gap the command center names, the concrete way to close
it: assign an available candidate, reskill a near miss who holds an adjacent skill,
reassign a strong fit from a lower priority requirement, or flag for external sourcing.
2. Optimize the whole bench. Allocate the bench across all open requirements at once to
maximize revenue protected, surfacing the contention when one scarce candidate tops
several gaps.
3. Proactive matching. Per available candidate, the best fit opportunities, plus a standing
watch that alerts when a newly available or newly certified candidate unlocks a gap that
was previously unfillable.
## 2. Non negotiable constraints, and how W3 holds each
1. No Python anywhere. W3 is pure Go. The optimizer is a pure Go minimum cost flow solver,
no cgo, no native math library. Any generation runs out of process on the existing
MEGAMIND plane over HTTP.
2. FIPS intact. The API binary stays `CGO_ENABLED=0 GOFIPS140=v1.0.0`. The optimizer adds
no dependency and no cgo. The FIPS stamp is verified after every build.
3. EEO isolation absolute. The recommendation core reads no demographic field. The
`internal/modules/ai` EEO unreachability tripwire (`TestNoAIFileReferencesEEO`) extends
to every new W3 source file, and a new test asserts the recommendation core takes no
protected attribute as input. `safety.ForbidEEO` guards every string sent to the plane.
4. Tenant isolation. W3 runs entirely inside `RunInTenantTx`, RLS scoped, on the validated
org from the session. The MEGAMIND plane stays stateless and persists nothing about any
recommendation.
5. The deterministic engine is the floor. Eligibility, the six component scores, the band,
and the rank within a gap come only from `engine.ScoreCandidate`. W3 never recomputes a
score and never overrides one. The optimizer arbitrates allocation among candidates the
engine already qualified, it never qualifies or disqualifies anyone.
6. Explainable, human in the loop, never auto reject. Every recommendation traces to frozen
engine numbers and explicit rules. A person approves or rejects each one. Rejecting an
assign recommendation only dismisses that suggestion, it never blacklists the candidate.
A source recommendation is a gap coverage note, never a decision about a person.
7. Both cloud portable. No cloud specific primitive. The proactive refresh uses the existing
scheduled job pattern (cron on the host or a systemd timer) with Postgres side change
detection, no Kafka, SQS, or Event Grid.
## 3. The recommendation core
Input: the org's open requirements (the W2 gaps) and the bench. The core asks the engine to
score the relevant candidate by requirement pairs (reusing `engine.ScoreCandidate`,
persisting each to `candidate_evaluations` so the score is frozen and referenceable), then
adds four deterministic outputs on top of that frozen matrix.
### 3.1 Action classification (deterministic)
For a candidate against a gap, the recommended action is decided by explicit rules, in this
order:
- `ASSIGN`: the candidate is available, clears the band threshold (Green, or Yellow if the
org allows Yellow staffing, configurable, default Yellow 75 and up), and is not already
committed to a higher priority requirement.
- `REASSIGN`: the candidate clears the band but is currently committed to a lower priority
or lower dollar requirement than this gap. The recommendation names both requirements and
the priority delta.
- `RESKILL`: the candidate falls short only on the skills component, is otherwise eligible
(clearance, availability), and holds a skill adjacent to a missing required skill above the
adjacency threshold, found through the live `scaffolds.SkillAdjacency` over the
`skills.embedding` HNSW index. The recommendation names the held skill, the missing skill,
and the adjacency distance.
- `SOURCE`: after the eligible bench is exhausted for the open slots, the remaining slots
recommend external sourcing. This is a gap coverage note, it names no candidate and rejects
no one.
`TEAM` (recommend a partner or subcontractor through the teaming graph) is out of scope for
v1 because GraphRAG teaming is still a scaffold. The action enum reserves the value so the
schema does not change when it lands.
### 3.2 Ranking and confidence (deterministic)
Within a gap, recommendations rank by the engine total descending, then by action priority
(assign, reassign, reskill, source), then by candidate id for a stable order.
Confidence is derived deterministically, not learned: a function of the engine score margin
above the band floor, the clearance provenance (self reported scores lower than sponsor
verified or continuous vetting), and data completeness (a profile missing customer history
scores lower confidence). It is a transparency aid, never a probability and never an input
to the decision. The learned LTR reranker with SHAP from the AI layer Phase 8 stays a
sequenced future layer, it is not part of W3 v1.
### 3.3 Narrative (the only place the AI is used)
The orchestrator writes the human readable rationale for each recommendation, grounded only
in the engine component trace, the adjacency facts for a reskill, availability, and the
current assignment. It is faithfulness gated through the existing `inference.Client`
faithfulness check. If the gate cannot confirm the generated rationale against those facts,
the recommendation falls back to a deterministic rationale string assembled from the same
facts and records `rationale_source = deterministic`. The recommendation itself never
depends on the AI, so a plane outage (handled by the existing circuit breaker) degrades the
prose, never the correctness.
## 4. The three views
### 4.1 Close the named gaps (gap centric)
A command center gap (a labor category, a required clearance, a skill set, and a slot count)
resolves to its backing open requirement row, or rows where one labor category spans several
open requirements. The core scores the eligible bench against that requirement, classifies
and ranks the actions, and returns the ranked list. This is a direct read of the core for one
requirement.
### 4.2 Optimize the whole bench (portfolio, true optimizer)
Allocate the bench across all open requirements at once to maximize revenue protected.
Formulation, a maximum profit assignment solved as a pure Go minimum cost flow:
- Nodes: a source, one node per eligible candidate, one node per open requirement, a sink.
- Edges:
- source to each candidate, capacity 1, cost 0 (a candidate is assigned at most once).
- candidate i to requirement j, capacity 1, present only if the engine qualified i for j
(band at or above the staffing floor). The cost is the negative of the assignment value.
- requirement j to the sink, capacity equal to the open slot count for j, cost 0.
- Assignment value of i to j: a function of the frozen engine total (fit) and the
requirement priority (a function of the opportunity value or exposure and the readiness
impact). Values are scaled to int64 with a fixed precision and deterministic rounding so
the flow solver stays integer exact. Scoring stays decimal in the engine, only the
optimizer objective uses scaled integers, and that is an allocation step, not a score.
- Solve by successive shortest path augmentation, stopping when the next augmenting path has
non negative cost (no further profitable assignment). Ties are broken by a fixed node order
(candidate id, then requirement id) so the result is deterministic. Unfilled slots and
unassigned candidates are allowed and natural in this formulation, unfilled slots become
`SOURCE` recommendations.
The optimizer never qualifies or disqualifies a candidate. Exclusion from an assignment is
always either the engine's deterministic band (not eligible) or the optimizer arbitrating
contention among the qualified to maximize the transparent objective.
Per assignment explanation, computed from the solution, not from dual or shadow prices:
- The assigned candidate's engine score for the assigned requirement (why qualified).
- The candidate's next best alternative requirement and the value delta (the opportunity
cost of placing them here).
- The requirement's next best candidate if this one were removed, and the score delta (why
this candidate over the next).
The AI narrates that counterfactual in plain language, faithfulness gated against the
computed numbers. Example: "Assigned J. Okafor to the intelligence analyst gap. They also
qualified for the targeting gap at 88, but targeting is well covered by R. Vance at 88 while
the intelligence analyst gap has no comparable backup, so this allocation protects 0.6M
dollars more."
### 4.3 Proactive matching (candidate centric, plus a watch)
For each available candidate, the best fit open opportunities, ranked by engine total. A
scheduled recompute (section 7) detects changes to availability, certifications, clearance
status, or new opportunity ingestion, and raises an alert when a change unlocks a gap that
had no eligible bench before. The alert is a recommendation row with the triggering change
recorded.
## 5. Persistence
Two new RLS forced tables, org scoped, composite foreign keys, candidate scoped for erasure.
`recommendation_runs`: id, organization_id, view (enum gap, portfolio, proactive), scope_ref
(the requirement id for a gap run, null for portfolio, the candidate id for a proactive run),
model_version (the frozen engine version plus the W3 logic version), created_by, created_at,
parameters (JSON, the thresholds and the staffing floor used).
`staffing_recommendations`: id, organization_id, run_id (foreign key to recommendation_runs),
requirement_id, candidate_id (null for source), action (enum assign, reassign, reskill,
source, team), rank, confidence (decimal), engine_evaluation_id (foreign key to
candidate_evaluations, the frozen score), value_score (the int64 scaled optimizer value for a
portfolio run, null otherwise), rationale (text), rationale_source (enum ai_faithful,
deterministic), evidence (JSON, the adjacency facts for a reskill, the reassign source
requirement, or the portfolio counterfactual), status (enum pending, approved, rejected,
dismissed, superseded), decided_by, decided_at, decision_note, created_at. The decision
columns mirror `slate_members` so the existing approve and reject UI and audit pattern carry
over. Erasure (`sourcing.Delete` and the anonymize in place path) nulls or removes a
candidate's recommendation rows, joining the existing `Memory.ForgetCandidate` cleanup.
Migration number follows the current head (the AI layer left the shared database at goose
v17, so this is 0018, plus the matching eeo set unchanged).
## 6. Determinism boundary, restated for the spec reader
The decision content of every recommendation (who, what action, what rank, what confidence,
and for the portfolio view which requirement) is computed only from frozen engine outputs,
the explicit action rules, the skill adjacency, availability, current assignment, and the
deterministic optimizer. No model sits in that path. The AI produces only the natural
language rationale, and only when the faithfulness gate confirms it against those same facts.
## 7. Triggers and refresh (both cloud portable)
- On demand: the gap and portfolio views compute on request.
- Proactive watch: a scheduled recompute, run by the existing host cron or a systemd timer
(the same pattern as `mm-opp-sync` and `mm-sam-sync`), no cloud specific event service. It
detects relevant changes through Postgres side comparison (a candidate or opportunity
updated since the last run), recomputes affected scopes, and writes new recommendation rows
and alerts. The recompute is idempotent and writes a fresh run rather than mutating prior
rows (prior rows move to `superseded`).
## 8. AEDT audit and the human in the loop flow
- A run emits `aedt.staffing.recommended` on the tenant transaction: run id, view, scope ref,
per action counts, model version. No PII, no names, no demographics, no rationale text.
- A human decision emits `aedt.staffing.decided`: the recommendation id, the action, the
decision, and a has_note flag. The note text is never in the payload (the slate decision
convention).
- Approving an assign recommendation can flow into the existing slate decision (link the
recommendation to a slate member) or record the assignment, depending on whether a slate
exists for the requirement. Rejecting only dismisses the suggestion. Never auto reject
holds throughout, the system proposes, a person disposes.
## 9. EEO safety
- The recommendation core, the action classifier, the optimizer, and the value function take
no demographic input and reference no eeo table or column. sqlc models no eeo table, so the
new queries cannot name one.
- `safety.ForbidEEO` guards every string passed to the plane for narration.
- `TestNoAIFileReferencesEEO` (the existing tripwire) walks the new W3 source files and fails
if any executable line references the eeo schema.
- A new test asserts the recommendation core's public input types contain no protected
attribute field, the same shape as the existing engine `Candidate` no demographic test.
## 10. API surface
New routes under the tenant scoped group, behind the session resolver, CSRF, RBAC, and the
same audit. Mounted under the `slatematch` and `missionmatch` namespaces as fits the view.
- `POST /recommendations/gap/{requirementID}` returns the ranked actions for one gap.
- `POST /recommendations/portfolio` returns the optimized allocation with per assignment
explanations.
- `GET /recommendations/proactive` returns the current bench watch alerts and per candidate
best fits.
- `POST /recommendations/{recommendationID}/decision` records approve, reject, or dismiss
(the slate decision pattern).
RBAC: a new capability `staffing.recommend` (granted to the roles that already hold
`slate.edit`) gates the three generating endpoints. The decision endpoint reuses the slate
decision capability. Read of recommendations reuses `candidate.read`.
## 11. Frontend
- Command center: each named gap gets a recommended actions expander (the gap centric view),
and the staffing gaps panel gets an optimize bench action that opens the portfolio
allocation view with the per assignment explanations and the contention notes.
- Candidates page: a bench watch panel (the proactive alerts) and a per candidate best fits
section.
- New TanStack Query hooks in the slatematch and missionmatch query modules, with approve,
reject, and dismiss mutations that invalidate the command center and candidates caches.
- The decision UI reuses the slate member approve and reject component, including the note
input.
## 12. Testing strategy
- Unit, pure logic, no database:
- The action classifier: golden cases for assign, reassign, reskill, source, including the
band floor boundary and the adjacency threshold boundary.
- The optimizer: determinism (same input, same allocation), correctness on small hand
checked instances, tie breaking, unfilled slots become source, and a property test that
no assigned candidate was below the engine band floor.
- Confidence: monotonic in score margin and provenance.
- Unit, safety:
- The EEO unreachability tripwire extended to the W3 files.
- The no protected attribute input test on the core types.
- Integration on M4 (the `integration` build tag, against the live Postgres):
- End to end gap view, portfolio view, and proactive view against seeded data, asserting
every recommendation references a real frozen `candidate_evaluations` row.
- The faithfulness fallback path (force an unfaithful narrative, assert
`rationale_source = deterministic` and the recommendation still stands).
- Erasure removes a candidate's recommendations.
- The decision flow writes `aedt.staffing.decided` and never auto rejects.
- Build gates: FIPS stamp after build, `make ci-gates`, the backdoor and EEO gates green.
## 13. Out of scope for v1, sequenced
- `TEAM` recommendations through the teaming graph (waits on GraphRAG teaming leaving
scaffold).
- The learned LTR reranker with SHAP on top of the engine (waits on labeled decision history,
the AI layer Phase 8 sequencing).
- A learned confidence or win probability (waits on labeled win and loss history, the AI
layer Phase 9 sequencing).
- Auto creation of training plans for a reskill recommendation (v1 names the gap and the
adjacency, it does not author a curriculum).
## 14. Decisions made during design
- Scope: all three views, built as one recommendation core seen from three angles, not three
separate features.
- Portfolio allocation: a true optimizer (pure Go minimum cost flow), not an explainable
greedy heuristic. Explainability is preserved by keeping eligibility deterministic in the
engine and by generating a plain language counterfactual per assignment from the value
matrix rather than exposing solver internals.
- The AI is confined to narration behind a faithfulness gate, with a deterministic fallback.
No model is in the decision path.