Written for Codex to pick up and run directly. Self-contained — the steps below don't require reading anything else first — but background links are included in case they help.
Two possible paths into this notes system; use whichever is live in your session. Either works for both reading and writing:
• MCP notes connector, if configured — see MEMORY/codex for known auth quirks (stale bearer tokens vs OAuth credential).
• The notes CLI over the gdata-server HTTP API — see README/command-line-tools (notes read, notes load -d, notes list).
Test whether matching-pursuit concept extraction (the design in Concept Factorisation) produces sensible word-labels for real notes in this corpus, before committing to either of that note's two open design questions. This is a feasibility check, not the real build — keep it small.
• Concept Factorisation & Hierarchical Indices — the design this prototypes: matching pursuit decomposes a note's embedding into 2–3 dictionary-atom words plus a salience weight each, instead of one averaged point.
• Representation, Not Language (see "The Amplified Bible as a Pre-Theoretic Case") — the intuition this grew from: an Amplified Bible bracket-gloss is matching pursuit done by hand.
• gloss — this project's index.
1. Build a small candidate dictionary. ~40–80 short words/phrases. Draw them informally from existing note tags and keys (notes list gives you the full key list to skim) rather than designing a canonical vocabulary — that's deliberately out of scope for this pass. Exclude stopwords/function words (articles, prepositions, pronouns, common auxiliaries, negators like "not"/"no") — a bare function word has no concentrated direction to match against (most notes brush against it about equally), so it just adds noise rather than a usable atom. This mostly happens for free since tags/keys are already content words; treat it as an explicit filter for anything else added by hand. Then dedupe the candidates against each other: compute pairwise cosine similarity (and magnitude) across the whole set. This isn't about whether two words' vectors genuinely differ — grammatical variants like number and degree are probably real, fairly consistent directions in the space (the same kind of structure behind classic word-analogy offsets like king−man+woman≈queen), not noise. It's about whether this dictionary needs the distinction. Plurals are the clearest case: "note" and "notes" likely differ by a genuine "multiplicity" component, but that component usually isn't part of what a note is topically about — collapse them to one atom as a working default for this purpose, not because the distinction is empty. Degree variants like "fast"/"faster"/"fastest" are the opposite default — the degree is often part of the actual topic — so leave those separate (see step 3). Treat both as defaults, not laws: flag any sample note (step 5) where a collapsed distinction looks like it mattered after all. There's no principled threshold for exactly where to draw this line — treat that itself as worth reporting on (see Deliverable), a small, cheap first look at the canonical-primes question Concept Factorisation already flags as unresolved, not a full solution to it.
2. Pick 8–10 sample notes spanning different topics. Suggested starting spread (substitute freely — topic diversity matters more than this exact list): PROGRAMMING_RULES/philosophy, PROGRAMMING_RULES/exceptions, ideas/concept-factorisation, first-thoughts/representation-not-language, gdata-server/notes/design, envoy/design-phases, README/orphaning, TFG/exercise-demo-protocol, using-gps-data. PROGRAMMING_RULES/exceptions is included deliberately — its meaning turns on a negation (don't suppress exceptions), which is a useful stress-test; see step 5.
3. Embed the dictionary and each sample note once, using the raw text as-is. Do not stem or lemmatize first. That's a workaround from bag-of-words/TF-IDF-era pipelines, where "fast", "faster" and "fastest" had to be forced to the same string before a count-based method could recognise them as related. Passage embedding models don't have that problem — they already place morphological variants close together in direction while preserving the genuine differences between them (comparative/superlative degree, tense, number), which is exactly the multiplicity this whole approach is trying to keep, not lose. Stemming first would quietly re-introduce the same centroid-collapse problem already flagged and resolved for the Amplified Bible fork (see Representation, Not Language) — only this time destroying the distinction before the notes even get a fair comparison. Use whatever embedding model/API is available in your environment (e.g. an OpenAI embedding model, or a local sentence-transformers model) — this prototype doesn't depend on which, but record which one you used in the results, since a later canonical version would need consistency.
4. Run plain matching pursuit per note, up to 3 iterations: cosine-select the best-matching dictionary atom against the current residual → record it with a weight equal to the projection magnitude → subtract that atom's contribution from the residual → stop early if ‖residual‖/‖original‖ drops below roughly 0.5. Orthogonal matching pursuit is deliberately not required here — whether it's needed is one of the two things this prototype is meant to inform, not something to resolve up front.
5. Eyeball each result. Does the 2–3-word gloss look like a sensible description of what the note is about? Note where it doesn't, and a guess at why (dictionary missing the right term, an unintuitive weight, the wrong atom picked). Specifically flag any note whose meaning turns on a negation — dense embeddings are known to handle negation poorly ("not X" often lands closer to "X" than to its opposite, since negation usually isn't a clean linear operation in these spaces). Whether the gloss for PROGRAMMING_RULES/exceptions captures the "don't do X" framing or just picks up "X" is worth recording as a data point — not something to fix in this pass by, say, sign-flipping negated atoms. That's a plausible-sounding fix but not one to bake in on a hypothesis; better to see what the evidence actually shows first.
Write results to a new note at gloss/prototype-results-2026-09-XX (use the actual date), one section per sample note: the note's key, its extracted (word, weight) list, and your eyeball verdict. Also record any near-duplicate merges made while building the dictionary (step 1) and roughly where you drew the line between collapsing and keeping distinct — a first, cheap data point on the canonical-primes question, separate from the two TBDs below. Close with a short overall verdict — worth pursuing further or not, and whether the evidence leans either way on the two open TBDs in Concept Factorisation (dictionary: open-extract vs snap-to-canonical; subtraction: plain vs orthogonal matching pursuit).
Then link the new note from gloss: read it first, preserve its existing content and links, add a line linking the results note, increment its version. See README/workflow and README/orphaning — don't leave the results note orphaned.
No Layer-1 hierarchical index, no canonical concept vocabulary/lattice, no decision on how the concept index would eventually be stored in gdata-server. This step answers one question only: do the extracted labels look sensible on real notes.