This is the admin console for the Matchmaking Intelligence Platform, a Level 1 matching, capacity, and decision layer that's deterministic end to end -- add entities, then use Match to rank candidates for a requester with one score blending semantic fit and two-way reciprocal interest, always explained, never a black box. Raw identity never leaves the gateway; the matching engine only ever sees anonymous tokens.
How to use this site
- Ingest. Click a sample-data button to ingest it straight away, or download a CSV template, fill it in, and upload it -- entering entities one at a time is available too, as an option.
- Match runs automatically. As soon as ingest finishes, you land on ranked, explained results with default settings -- no setup required first.
- Review. Check Snapshots to see how a ranking changed, and record Feedback on what happened to each result.
- Tune (optional). Not happy with the results? Set ranking rules in Instructions (e.g. “prefer fintech”) or mark entity Availability, then re-run the match to see the effect.
Match, Review, and Tune are meant to be revisited, not done once: check a result, adjust a rule in Tune, re-run Match, check the outcome again -- so you always see what effect a change actually had.
Every design decision below traces to a named paper, standard, or spec section -- and to the file that implements it. Nothing here is retrofitted: the platform's spec cited its research foundations before a line of code existed.
The build follows two layers of grounding. Tier A is the platform's own stated research foundations -- written into Matchmaking_Intelligence_Platform_Revision_5.md §19 as design principles, each already citing sources, before implementation began. Tier B is the algorithm level: the specific published method or standard each running module actually follows.
Grounding is not the same as completeness. CLAUDE.md scopes this build to Level 1 matching, capacity, and a deterministic decision layer -- explicitly excluding learned ranking and graph methods. Where a cited principle points toward something out of that scope, it is marked deferred below rather than quietly skipped or overclaimed.
implemented running in the code, file exists and is tested · partial the principle is honored in part · deferred intentionally out of scope per CLAUDE.md
I. Why -- the platform's stated research foundations
Thirteen of the eighteen design principles in spec §19 map to a concrete piece of this build.
| Principle | Grounded in | Status |
|---|---|---|
| Two-sided reciprocal markets §19.2 Both sides have to want the match -- a great candidate who doesn't want what's on offer isn't actually a good match. engine/scoring/directional.py -- a→b and b→a scored separately, combined by harmonic mean | R1, R2, R3 | implemented |
| Reciprocity must be directional §19.16 What A needs from B differs from what B needs from A, so each direction is checked on its own before the two are combined. engine/scoring/directional.py -- needs→capabilities and preferences→opportunity compared separately, never symmetric similarity alone | R3 | implemented |
| Rank, don't just classify §19.3 The goal is ordering candidates best-to-worst for a specific ask -- not just sorting them into "good" and "bad" piles. Every response returns ordered candidates via a deterministic weighted score + MMR -- not a learned ranker. learned: null on every response, per hard rule 1. | R4 | deferred |
| Beyond accuracy: diversity & serendipity §19.4-19.5 A list that's technically accurate but shows five near-identical candidates isn't actually useful, so the system deliberately mixes in variety. engine/rerank/mmr.py -- λ=0.7 default, 0.5 under the "exploratory" strategy control | R5, R6, R7 | implemented |
| Guard exposure / popularity feedback loops §19.6 If the same few entities get shown over and over, they start looking "popular" just because they were shown a lot, not because they're better. engine/capacity/, evals/evals/exposure.py -- exposure counters (30/entity/7d), congestion discount, top-5%-share report | R8 | implemented |
| Model multiple stakeholders §19.7 A match affects more than the person asking for it -- the person recommended, the project owner, and the platform all have a stake. Capacity/exclusion logic weighs both sides of a match; no separate multi-stakeholder optimization objective is computed. | R9 | partial |
| Constraint / preference / intent / strategy / presentation taxonomy §19.9 "Must have X" means something different from "prefer X," which is different from "show me more options." shared/mip_shared/policy_validation.py -- precedence app > project > user, tighten-only; preferences rerank, never silently filter | R10 | implemented |
| Separate compatibility, feasibility, outcome §19.10 Being a great fit on paper, actually being available right now, and being likely to succeed are three different questions -- kept as three different answers. Base score, capacity exclusion, and (absent) outcome probability kept as distinct fields across the base/adjusted/delivered snapshots. | — | implemented |
| Scores are not calibrated probabilities §19.11 A score of 82 doesn't mean "an 82% chance of success" -- it just means this candidate ranks above one scored 75. Satisfied by omission -- no probability head exists; responses expose ordinal scores only. | R6 | implemented |
| Explanation, counterfactuals, controllability §19.12 Every result comes with a plain reason it ranked where it did, and what would need to change for it to rank higher. engine/explain/ -- template explanations + counterfactuals, capped at 2 per result | R10, R14 | implemented |
| Graph augments, doesn't replace §19.15 Looking at who's connected to whom could add a useful signal later -- but it's not built yet. Explicitly out of scope -- CLAUDE.md hard rule 1: no Levels 2-4 or graph. | R11 | deferred |
| De-identification limits in small populations §19.17 In a small market, even "anonymous" details can accidentally point to one real person. Removing names alone isn't automatically enough. Tokenization + vault encryption implemented; explicit k-anonymity thresholding of quasi-identifiers for a released analytics corpus is not yet built. | R13 | partial |
| Evidence provenance & uncertainty as first-class §19.18 The system tracks not just what it knows about someone, but how sure it is and where that information came from. engine/scoring/confidence.py -- evidence confidence value carried per result, distinct from compatibility | R6, R10 | implemented |
II. How -- algorithms behind the running code
Where the code is a faithful implementation of the cited method, that's stated plainly. Where it follows the same problem framing with a simpler mechanism, that's stated too.
| Technique | Reference |
|---|---|
| Diversity reranking (MMR) After ranking by relevance, the list gets reshuffled slightly so it doesn't show five near-duplicates in a row. engine/rerank/mmr.py -- direct implementation of the original formula: λ·sim(d,q) − (1−λ)·max sim(d, selected) | I1 |
| Weighted hybrid base score The final score blends semantic similarity and reciprocal-fit signal in a fixed, adjustable ratio. engine/scoring/directional.py §5.2 -- w_sem·semantic + w_rec·reciprocal, a "weighted hybridization" in Burke's taxonomy | I5 |
| Directional reciprocal aggregation Two one-way scores are combined so a lopsided match pulls the final score down, instead of a strong one-sided score hiding a weak other side. engine/scoring/directional.py -- harmonic mean of a→b, b→a | R3 |
| Sentence embeddings Turns each text profile into a list of numbers that captures its meaning, so "similar meaning" becomes measurable. worker/app/embeddings.py -- pinned bge-small-en-v1.5 (I2); descends from the SBERT siamese bi-encoder paradigm (I4, lineage) | I2, I4 |
| Approximate nearest-neighbor retrieval Instead of comparing a candidate against every profile in the database, an index quickly finds the ~100 most likely matches first. engine/scoring/db.py -- pgvector index backing the top-100 candidate set, the HNSW graph-search family | I3 |
| Deterministic pseudonymization Turns a name into a fixed, non-reversible code -- the same person always gets the same code, but the code alone can't be turned back into the name. gateway tokenizer -- per-tenant entity_token (ENT_<12 hex>), keyed and deterministic | I6 |
| Exposure / position fairness Being shown near the top of a list isn't free -- it uses up a limited "exposure budget," so the same top candidates aren't shown to everyone forever. engine/capacity/ -- same problem framing as I8, a simpler mechanism (fixed budget + rotation, not an LP-based optimizer) | I8 |
| Rank-agreement evaluation Compares the system's ranking to a human expert's ranking of the same candidates, and produces one number for how closely they agree. evals/evals/agreement.py -- Kendall's τ via scipy.stats.kendalltau, engine ranking vs. blind expert panel | I7 |
| Deterministic, non-learned decision layer The ranking math never calls an AI model -- it's fixed arithmetic every time, so identical inputs always produce the identical output. CLAUDE.md hard rule 4 -- "no LLM calls inside scoring, ranking, policy application, explanation, or counterfactuals" | I9 |
III. Regulatory & standards anchors
Not academic papers, but the specific legal and technical standards the privacy design is built against.
- RFC 2104 -- HMAC keyed-hashing
- The construction behind deterministic entity tokenization (I6). Plainly: a one-way, key-locked scrambler for turning a name into a code.
- RFC 4880 -- OpenPGP message format
- The encryption scheme pgcrypto implements for the per-tenant identity vault. Plainly: the lockbox format the real names are stored in.
- GDPR Art. 4(5) -- definition of pseudonymization
- The legal definition the token design is built to satisfy. Plainly: data that can't be traced back to a person without a separate, protected key.
- GDPR Art. 22 & Art. 25 -- automated-decision transparency, privacy by design
- Motivates the deterministic scoring pipeline and the explanation/counterfactual trail on every result.
- Quebec Law 25
- Cited directly in the platform spec (§19.12) as the compliance context for explainability and controllability.
- HIPAA Safe Harbor, 45 CFR §164.514
- The closest legal analogue to "no raw identity past the gateway." Plainly: a defined line past which identifying details are not allowed to cross.
IV. References
R1-R14 are reproduced from the platform spec's own §21. I1-I9 are added here, at the implementation level, and independently verified.
Design rationale
- R1Gale, D., & Shapley, L. S. (1962). College Admissions and the Stability of Marriage. The American Mathematical Monthly, 69(1), 9-15.The original proof that two groups with different preferences can always be paired up so no pair would rather swap partners -- the founding result of matching theory.
- R2The Royal Swedish Academy of Sciences. (2012). Stable Allocations and the Practice of Market Design. Scientific Background, Sveriges Riksbank Prize in Economic Sciences.The Nobel committee's own explainer for why the 2012 Economics Prize (Roth & Shapley) mattered.
- R3Palomares, I. (2020). Reciprocal Recommendation: Matching Users with the Right Users. SIGIR '20, 2429-2431.A short survey defining what makes a recommendation "reciprocal" -- both people have to like the match, not just one.
- R4Swezey, R. M. E., Grover, A., Charron, B., & Ermon, S. (2021). PiRank: Scalable Learning to Rank via Differentiable Sorting. NeurIPS 34.A machine-learning technique for training a ranking model to directly optimize list order.
- R5Kaminskas, M., & Bridge, D. (2016). Diversity, Serendipity, Novelty, and Coverage. ACM TiiS, 7(1), Art. 2.Argues recommender systems should be judged on more than accuracy alone.
- R6Steck, H. (2018). Calibrated Recommendations. RecSys '18, 154-162.Netflix research showing recommendations should mirror the real mix of a person's taste, not just their single favorite genre.
- R7Zangerle, E., & Bauer, C. (2022). Evaluating Recommender Systems: Survey and Framework. ACM Computing Surveys, 55(8), Art. 170.A survey of the many ways researchers evaluate recommender systems.
- R8Mansoury, M., Abdollahpouri, H., Pechenizkiy, M., Mobasher, B., & Burke, R. (2020). Feedback Loop and Bias Amplification in Recommender Systems. CIKM '20.Shows recommenders can create a feedback loop where showing something more makes it look more popular.
- R9Ranjbar Kermany, N., et al. (2021). A Fairness-Aware Multi-Stakeholder Recommender System. World Wide Web.A recommender system designed to be fair to everyone affected by the recommendation, not just the searcher.
- R10Ge, Y., et al. (2024). A Survey on Trustworthy Recommender Systems. ACM Transactions on Recommender Systems.Defines "trustworthy": fairness, privacy, explainability, and robustness as one connected package.
- R11Duricic, T., Kowald, D., Lacic, E., & Lex, E. (2023). Beyond-Accuracy: Diversity, Serendipity and Fairness in Recommender Systems Based on Graph Neural Networks.A survey on using graph methods to add diversity and fairness to recommendations.
- R12Chen, J., Dong, H., Wang, X., Feng, F., Wang, M., & He, X. (2020). Bias and Debias in Recommender System.A catalogue of biases that creep into recommender systems, and ways to correct for them.
- R13Sweeney, L. (2002). k-Anonymity: A Model for Protecting Privacy. Intl. J. of Uncertainty, Fuzziness and Knowledge-Based Systems, 10(5), 557-570.Defines "k-anonymity": a record is only anonymous if indistinguishable from at least k-1 others.
- R14Wachter, S., Mittelstadt, B., & Russell, C. (2018). Counterfactual Explanations Without Opening the Black Box. Harvard J. of Law & Technology, 31(2), 841-887.Argues people are entitled to a counterfactual explanation of an automated decision under GDPR.
Implementation-level
- I1Carbonell, J., & Goldstein, J. (1998). The Use of MMR, Diversity-Based Reranking. SIGIR '98, 335-336.The original MMR formula for balancing relevance against redundancy in a ranked list.
- I2Xiao, S., Liu, Z., Zhang, P., & Muennighoff, N. (2023). C-Pack: Packaged Resources to Advance General Chinese Embedding.The paper behind the BGE embedding model family, including bge-small-en-v1.5, used here.
- I3Malkov, Y. A., & Yashunin, D. A. (2016). Efficient and Robust ANN Search Using HNSW Graphs. IEEE TPAMI (2018).The search-index technique behind fast nearest-neighbor lookup among millions of vectors.
- I4Reimers, N., & Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings Using Siamese BERT-Networks. EMNLP-IJCNLP 2019.Showed how to adapt language models so similar-meaning text yields similar vectors -- the lineage this platform's embeddings build on.
- I5Burke, R. (2002). Hybrid Recommender Systems: Survey and Experiments. User Modeling and User-Adapted Interaction, 12(4), 331-370.A survey of ways to combine multiple recommendation signals into one score.
- I6Krawczyk, H., Bellare, M., & Canetti, R. (1997). HMAC: Keyed-Hashing for Message Authentication. IETF RFC 2104.The internet standard behind this platform's tokenization.
- I7Kendall, M. G. (1938). A New Measure of Rank Correlation. Biometrika, 30(1/2), 81-93.The original statistic for measuring agreement between two rankings.
- I8Singh, A., & Joachims, T. (2018). Fairness of Exposure in Rankings. KDD '18, 2219-2228.Argues top-of-list exposure is a scarce resource that should be shared out fairly over time.
- I9Rudin, C. (2019). Stop Explaining Black Box ML Models for High Stakes Decisions. Nature Machine Intelligence, 1(5), 206-215.Argues high-stakes decisions should use interpretable models from the start, not a black box explained after the fact.
Ingest entities
Startups match against advisors; nonprofits match against funders -- those are the two pairs this platform runs today. Keep a tenant to one pair: the engine ranks any entity of a different kind as a candidate, so mixing all four in one tenant still returns results, they just won't mean anything.
1. Try it with sample data
Ingests ready-made, realistic sample data straight into the tenant below -- no download/upload round trip -- and matching runs automatically right after.
Prefer a CSV file? Download one instead (e.g. to inspect the format, or edit before uploading below):
2. Upload & ingest
Columns (case-insensitive, only name required): name, org, email, kind, industry, stage, profile, needs, capabilities, preferences, opportunity. A row's own kind column (if present) overrides the default kind below -- useful for a mixed file. Parsed and sent as one batch; each row runs the same PII pipeline as a single ingest, and one bad row won't lose the rest.
Matching runs automatically as soon as ingest finishes -- you'll land on the results with default settings, no setup required. Tune (Instructions/Availability) is for adjusting those results afterward, not a prerequisite; change something there and re-run any time.
Enter one manually instead
Raw identity is sent to the gateway only; it's tokenized/de-identified before anything else ever sees it.
Recently ingested (this browser only)
Labels are kept in your browser's local storage for convenience only -- the backend never stores or returns raw identity after ingest.
Run a match
Runs automatically right after ingest, with default settings. Not happy with a result? Set a rule in Tune, then come back and re-run.
Batch match (many-to-many)
Runs the same match once per requester below -- retrieval already scopes each call to the opposite-kind pool in the tenant, so a list of startups against a list of funders is just "run match for every startup"; there's no separate many-to-many primitive to configure.
View a previously saved run
Re-load a results CSV downloaded above to view it again, without calling the API.
Interpret an instruction
Rules parser first, zero model calls for simple patterns (prefer/avoid/exclude/only show/focus on X). Nothing activates until you confirm.
Scope controls how broadly the rule applies. application = everyone in the tenant (scope ref is just the tenant ID again -- the usual choice). project = one project (scope ref is a project ID). user = one requester only (scope ref is their entity token -- use the quick-pick below).
Compare snapshots
See a rule's effect: compare base (before any policy) against delivered (after). If it's not what you wanted, go back to Tune.
Record feedback
Feedback is only accepted for a request_id with a delivered match -- run a match first. The easiest way is the feedback buttons already shown under each result on the Match page itself; use this form only if you don't have that screen open anymore.
Entity availability
Whether an entity currently shows up as a match candidate at all -- open/limited are included, paused/full are excluded. Pick a tenant + entity below, or use the quick-pick to fill both from something you've ingested.