Context Vigilance
The why beneath the code
Specs, habits, and reflections that shape how augment-it gets built. Versioned context, intentionally legible.
specs
SearchBox — LiveFilter and Autocomplete
A subsidiary spec. Two named variants over one private core, because the keyboard contract must exist exactly once and the two differ only in where options come from.
The component API contract and the control scale — inspired by shadcn, with sprinkles of Tailwind, derived from what members already built
Members were already converging on Tailwind's radius scale by instinct. They just had no token to spell it with.
Design System Convergence — the organ registry, its five verdicts, and the fingerprint ledger that catches drift while it happens
The registry is what makes drift legible: a declared organ is a decision, an undeclared one is drift. The code can be identical in both cases.
Federated Component Libraries
One gallery runtime, seventeen sovereign catalogs — every member publishes what it is made of, at its own address.
Source Content Storage — SurrealDB-Primary, Local as a Per-User Toggle
Flip the content store: the article body moves onto the canonical `sources` row and the local filesystem write demotes to a toggle.
Corpora Builder Harmony — the evolving test registry
Every proposed and implemented test guarding the corpora builder and the systems it must harmonize with — identity, workspace connector, transport, state, canonical layer, files — in human language, MECE, one ✓-phrase each.
Design System Portal
Specification for the portal that renders the federated design system — the swatch page, the token catalogue, the member index.
Federated Design System Architecture
The organising specification for augment-it's two-tier, seventeen-member design system.
Augment from DB — the Org Workbench + Search-and-Add flow: two new microfrontends over capabilities that mostly exist
Start from a canonical org, not a CSV row: an org workbench over links, streams, corpus and people, plus provider-pluggable search-and-add.
Entity-Card Edit & Remove Affordances — every visible property gets a micro-button pair
The org card views and edits in place, but only additively — a misclicked ➕ today required a direct database write to undo. Every entry and identity property the card shows grows ✎ and × micro-buttons.
Search-Results Queue — a right-rail microfrontend where concurrent agent searches land, signal, and get triaged
Agent searches run minutes; the operator shouldn't. Every search becomes a card in a persistent right rail — fire many, triage on arrival.
Connector Inventory & Per-Record Palette — Hot-Swap Providers, Re-Fire One Record at a Time
Per-record connector palette: click `f` to re-fire one row through the next Facebook provider, over a registry that resolves by capability.
Strategy Curator — An Entry-Point App for augment-it
A canonical source registry in SurrealDB owns identity, the client's filesystem owns usage, and a shared UUID is the only bond.
Entity-Pulse Bundle — Press Releases, News Mentions, and the Social Voice of a Record
Official Updates fires first; its rollup becomes the relevance prior for Media and Socials Mentions — a foundation-first four-phase DAG.
Pulse pattern — one operator burst against one entity, expressed as N independent pulse-dimensions composed in a pulse-surface, each dimension potentially owning its own microservice
Operators enrich in bursts, not steps: one search fills name, socials, emails, and org, and a pulse-surface commits all of it in one save.
Record ↔ DB Resolver — operator-driven match/create bridge from row-store records to canonical organizations
Row-store records and canonical SurrealDB orgs were never bridged; the resolver closes the gap one record at a time, operator driving.
Sparse-Person Enrichment Surface — per-email triage where the operator finds the human behind the address, picks or creates the org they belong to, and writes both back to the canonical layer
177 event attendees landed as 177 bare emails — the opposite shape from the URL-bearing records every other augment-it flow assumes.
Augment from Affiliations — the first flow that starts from SurrealDB instead of a CSV, turning an event's speaker/org pairs into a rated, sourced prospect list
The first flow that starts in the canonical layer, not a CSV: export an event's affiliations, rate relevance offline, reimport.
Workspaces as Tenant Primitive — toggling, tenant-aware microservices, per-tenant env-var pickup, and the seam that lets MCPs and connectors vary per client
`workspace` is the tenant boundary — humain-vc vs reach-edu. The vision is stated once, then step 1 is cut down to filesystem-only bones.
Client tagging on canonical writes — every observation carries the client that produced it, and every canonical entity carries the materialized set of clients that can see it
The canonical layer is cross-client by design — a materialized `client_access` array is how each workspace still sees only its own.
Records Surface sort step and UI — sort ships as part of the **Sort & Filter Lens**, the second lens in step 2's default set (alongside the existing **Pack Firing Lens**); `lens` is the architectural primitive this spec introduces and lenses are *swappable* (one active per step at a time), not stackable; each step ships with a small curated default lens set and the registry stays *open* so new lenses can join without architecture changes
Sort ships as the second swappable lens on step 2 — and the lens registry is open, so a new lens is a manifest drop, not an enum edit.
Chat Context-Awareness Architecture — three layers (workspace as context broker, slab-assembly contract, verb registry) that grow the in-app chat from prompt-only to surface-aware verb router
Chat's verb roster is a hand-written prose block and its context slab carries only `record_set_id`; this closes both holes.
Corpus Inbox — capture first, triage later; a zero-friction save destination for URLs without a home yet, with a future triage layer that sorts inbox content into the right places
A URL with no home yet shouldn't cost a filing decision: `corpus/inbox/` captures the page, its body, and a drive-by note, then waits.
Funder Content Corpus Workflow — what the system has to do, ranked by quality bar, with no implementation prescribed
Written so a future agent resists the pull to filter yesterday's bad data tighter instead of firing fresh for today's good data.
Record-Set Family Grouping — internal lineage vs. external-variant families in the Record Collector sidebar
The sidebar shows a tracker uploaded as v4–v8 as five unrelated CSVs. Two family kinds — promotion lineage and external variant — fix that.
Response Reviewer Shell and Content-Reader Mode — Response Reviewer becomes a wrapper whose inner review UI swaps based on what the bundle that fired actually produced
1,109 OfficialPulse responses, 3 accepts: 'is this URL right?' is the wrong question for content packs, so review mode becomes swappable.
Flow for Bundles & Packs — The Simplest Possible Thing
For 67 rows with a website URL, find each one's blog index. Two surfaces, no reviewers — this spec deliberately ignores the five before it.
Per-Record Iteration as the Primary Surface for Pack and Bundle Fires — The Flow Rearranges Per Fire Type
A pack fired across 96 rows returned 0 found — so per-record iteration becomes primary and bulk fan-out waits until a chain is proven.
Pulse Curation Layer & UI — Three Layers per Category, Triage Per Item, Finalize on Demand
Three layers per category: immutable `raw_output`, live `curated_output`, and a `finalized_output` snapshot locked when triage is done.
Shell & Micro-Frontend UX Coherence — Affordances That Are Found, Consistent, and Talk Back
A demo-prep chain of 'I can't find / reach / trigger X' is a verdict: the shell's affordances hide, die, or mismatch. Fix the pattern.
Tooltip System — A Versatile First-Class Family, Plus a Walkthrough for New and Returning Users
Apps fail at orientation, not functionality — so tooltips become a first-class family, not the browser's half-working `title=`.
Enhanced Records List — the Triage Checkpoint and the Promotion Loop
One record-grained view of a whole enrichment round: select the good rows, promote them to canonical, and the predecessors archive.
Request Reviewer — the Pre-Flight Surface
See exactly what is about to leave the building — and guarantee the request you reviewed is byte-identical to the one that fires.
Response Reviewer and Response Store — the Post-Flight Surface
No review surface until a fired response is a first-class stored object — so response-store and response-reviewer are specced as one.
Walking-Skeleton Pre-Flight Decisions — Augment-It Rewrite
Five substrate decisions — state, transport, persistence, auth, agent scaffolding — settled before code so no session re-walks the tree.
Augment-It as a CRM-Augmentation Pipeline (Microfrontends + Microservices)
memopop makes memos, dididecks makes slides, augment-it makes information that lands back in a CRM it doesn't own.
prompts
Common-Six Social Packs — First Real Packs on the Structured-Output Surface
Six pack identities — linkedin, x, bluesky, youtube, facebook, wikipedia — on one backend routing by `pack_id`, no microfrontend per pack.
Helpful Links on Records — Captured During Response-Reviewer Triage
The adjacent links a human finds while triaging die in the clipboard; `helpful_links` catches them in one click and survives derivations.
Response Reviewer — Structured-Output Extension (Packs-and-Bundles Foundation)
Build the surface every pack lands on — candidate cards, confidence pills, outcome enum — against mock fixtures. Zero packs ship here.
Run /speckit-specify — Response Reviewer Structured-Output Extension (Packs-and-Bundles Feature 1)
Feature 1 of the packs-and-bundles series: the structured-output surface every pack will land on. Zero packs, zero bundles implemented.
Build the Shell Tiling & Peek-Deck — Window the Federated Frontends
The shell stops being a tab switcher: a peek-deck at 90% width with neighbours peeking, plus a two-remote split with a draggable seam.
Run /speckit-constitution — Seed Augment-It's Constitution from Context-V
The directive to paste with /speckit-constitution so the principles synthesize from our own context-v docs, not from training data.
Run /speckit-specify — Workspace + Sidecar Foundation (Feature 001)
The workspace package and bun sidecar, plus exactly one capability — `records.import` — end to end to prove the pipe. No federation yet.
reminders
Libraries We Do Not Use — Ever
A hard denylist of packages this codebase has removed on purpose. Do not import them, do not assume they are installed, do not re-add them.
Tags Are Two Projections — Frontmatter `tags:` on Files, `has_tag` Observations in SurrealDB
Files say `tags:` because Obsidian reads files; the DB says `has_tag` because its predicates are verb-shaped. Same fact, two projections.
Record Count Stays Stable Across Versions — Augmenting Adds Columns, Never Rows
One dataset, one row count, forever — augmenting adds columns, not rows. 231 rows in the store for a 96-record dataset is a symptom.
explorations
The Gap Between What We Preach and What We Practiced
Forty deployable units, one git repo, zero component-level design systems or changelogs. An honest audit of augment-it against the three recommendations we make to clients.
Design Language Audit — July 2026
The hand-counted baseline audit that measured the state of augment-it's CSS before the design system shipped. Superseded as the counting mechanism by design-drift.mjs.
Augment from DB — the org-first workbench flow, and the two new microfrontends it needs
A flow that starts from SurrealDB, not a CSV: pick an org, reveal its people and pulse streams, augment through pluggable search packs.
augment-it has outgrown one flow — ROTATION is the CSV-augmentation pipeline's shape wearing a general-purpose name, and corpora-curator's promotion to its head is a splice, not a fit
ROTATION (`shell/src/remotes.ts`) is the CSV-augmentation flow hardcoded as THE nav — every other use case gets spliced onto it.
Syncthing for Collaborator Access to the Corpus (R2 Backup Already Decided)
R2 already won the backup leg — rclone, not a live mount. This is the separate, still-open question: could Syncthing give other humans live access to the same corpus, without breaking the single-writer discipline that's kept things sane so far?
The Moat Is Grounded Deliverable Production, Not Chat
Chat-over-documents is commoditizing; the moat is the last mile — a shippable deck or memo with every claim traceable to source.
Funder-Fit Engine — Org-Anchored Corpora and the Bidirectional Story↔Funder Cycle
Fundraising matches both ways — funder→story and story→funder — on one org-anchored corpus. The differentiator is KAG, not plain RAG.
Forced One-By-One Tag Selector — a pulse-dimension pattern for deliberate triage instead of lazy bulk-tick
Bulk checkboxes produce uniform half-considered tags. Present one tag at a time — apply / skip / skip-rest — and each decision gets made.
Joined People UI and the Network-First Pivot — augment-it's sibling-flow to org-first augmentation, and the canonical/proprietary layer split underneath it
Org-first and people-first are two pivots on one join — and the split that matters is canonical (shareable) vs proprietary (client-only).
Best Way to RAG Over the Corpus — design space for retrieval-augmented operations on augment-it's per-client corpus, given the structured frontmatter we just earned
245 corpus files carry `funder_slug` and `published_at`, so retrieval is facet-filter-first — embeddings handle the residual about-ness.
Inbox Sort by Agent Tasks — moving the inbox from a flat 86-item pending queue into a task-typed work surface where the operator sees what's next and the agent does the safe parts automatically
86 pending inbox files render identically, so the operator context-switches between four task types on every scroll.
Operator-built flows beyond the universal pipeline — the default augmentation path is a dud for most edge cases, and the cheaper-than-microfrontend escape is a view-spec the agent-chat composes from natural language and the UI renders generically
The default flow lands cleanly on 17 of 96 reach-edu records. The escape isn't a microfrontend per scenario — it's a generic spec-renderer.
In-App Browser vs Browser Plugin for Corpus Add — bridging the operator's own search into the per-record corpus without leaving the cockpit
Adding one operator-found URL to a funder's corpus is a ten-step round-trip out to Google and back. In-app browser, or browser plugin?
Per-Client Privacy and the Path Off Local — when does single-operator-local-only stop scaling, what stack do we reach for, and how do we architect today so the move is cheap when it comes
Per-client corpus privacy and a client wanting login hit the same week. Not a stack decision — which choices keep the move off local cheap.
Agent-Chat Skills and Commands — Candidates List
The chat's verb roster is four prompt-focused capabilities. A running list of shell scripts that should graduate into chat-callable verbs.
Augment-It Prior Art Survey — What's Already Been Built, and What It Tells Us
Two prior attempts exist — Tanuj's three federated repos and Michael's bolt monolith. Both cover the core; neither is what we ship.
Bolt-Era API Provider Widget Analysis
The bolt widget picked Claude, GPT, or Perplexity per prompt section. The widget dies in the rewrite; the multi-provider shape stays.
Bolt-Era Codebase Analysis
A faithful architectural map of the bolt monolith — React + TS + Vite + Supabase + zustand — lifted from its own `specs/` folder.
Bolt-Era Highlight Collector Analysis
The only existing description of the highlight-collector stage — one of two that never got split into Tanuj's microfrontend repos.
Bolt-Era Main Container UI Analysis
The bolt shell's five-column layout and auth gate — prior art for the rewrite's open question: one host shell, or a host per app?
Bolt Monolith As Built — The archive/bolt-code Branch
The earliest augment-it is a Vite + React monolith on `archive/bolt-code`: feature-richer than the federated repos, architecture we discard.
Bolt-Era Prompt Section Analysis
Prompt templates as MDX-rich, variable-aware, edit-toggle-preview blocks — the pattern prompt-template-manager should probably adopt.
Bolt-Era Record Collector Analysis
Cross-reference against `Tanuj-Record-Collector-As-Built` — the diff between bolt-era and forked shows which patterns survived federation.
Entity-Profile Augmentation Workflow — Common Social + Vertical-Specific Sources, Per Entity Type
Two tiers replace prompt-by-prompt column filling: packs as atomic source-bound units, bundles as workflow-shaped compositions of packs.
Federation and Bundler Decision — Bun + Rsbuild + Module Federation, Workspace State, Optional Chat
We federate: Module Federation on rsbuild, bun over turbo, and state of truth in `@augment-it/workspace` — chat is just one consumer.
Tanuj's Prompt-Manager As Built
Full CRUD-shaped prompt UI over a hardcoded `samplePrompts` array — no store, no data flow. Keep the schema, throw away the implementation.
Tanuj's Record-Collector As Built
The most-finished of Tanuj's three splits. One idea survives: the prompt template auto-generates from the imported CSV's columns.
Tanuj's Request-Reviewer As Built — The Module Federation Proof
The only place Tanuj got federation working — a shared `RecordCard` — while the augmentation logic sits copy-pasted from record-collector.
Multi-Agent Research Fan-Out Per Row — The Real Shape of Augment-It's Capability Runtime
Capabilities aren't LLM calls — five research agents run per row in parallel, so the runtime needs (rows × agents) fan-out.
issues
A component test whose fixture is simpler than its call sites
Selector--Menu's suite was green while both of its first two adopters were broken in exactly the way its header promises to prevent.
A silently ignored alias pointed a verification probe at production
rsbuild accepts source.alias and ignores it. Three agents rendered live data believing it was a fixture; one wrote a file into client corpus.
Issues raised by the migration subagent while converging request-reviewer
Findings surfaced while doing something else. Raised, not chased — the diff stays clean and the finding stays reviewable.
Structural invariants live in prose, so sweeps stop halfway and nothing notices
Three units have now been found whose typecheck had never once passed. Each was found by accident, five weeks apart, by someone tidying something else.
The federation has no layout layer, so seven of its eight deviations are about placement
The design system standardised everything that goes inside a box and nothing about the boxes. Consumers keep their freedom for now — deliberately, and on the record.
Every remote hardcodes the workspace WebSocket to localhost — Org Workbench loads no data on augment.didi.sh
Sixteen remotes dial `ws://localhost:3001/ws` with no env read. On prod that points at the visitor's own laptop, so the socket shows `closed` and the roster never fills.
Tokens landed, components didn't — the UI needs an overhaul, and the drift linter can't see the problem
19 of 20 apps consume the theme package; shared-ui ships exactly two components. Every remote hand-rolls its own buttons, pills, and empty states against shared colours.
A failed deploy is silent, so nothing watches production after merge
Every frontend Docker build failed for twelve days unnoticed: the old container keeps serving and the health check keeps passing.
Domain type is ambient state, so a failed workspace load hides every corpus
humain-vc opened the Corpora Curator and saw 'strategy' and 'No corpora yet' — it has theses, and plenty of them. One guessed value at load time silently filtered the whole surface, and the same symptom was debugged out once already on 2026-07-07.
One stuck message kills a NATS subject until restart — `domain.list: timeout` and the sequential handler loop
Every handler in `domains.ts` consumes its subject with a `for await` loop, so one unsettled request blocks the subject until a restart.
Move the rest of the app to remote hosting — prod still falls back to localhost for every undeployed remote
12 micro-frontends are hardcoded to `http://localhost:3XXX` in the prod shell, so augment.didi.sh fetches them from the visitor's machine.
Concurrent agent searches queue into a search-results column — fire many, deal with them as they come
Agent searches run 60–210s and each one hijacks a single column. Wanted: a rightmost queue where every fired search appends its own card.
Fetch full content clobbers the operator's metadata — resets the title to a URL approximation
`fetchSourceContent` never consulted the saved title, so Jina's guess — or the raw URL on failure — overwrote what the operator typed.
Jina metadata parser is blog-only — needs two profiles + fuzzy routing (academic sources lose their date/publisher)
The parser only reads OpenGraph keys, so scholarly sources lose date and publisher to `citation_*` / `dc.*` / `prism.*` it never looks at.
No test coverage — TDD keeps getting deferred, despite being exactly the right fit for agentic development
Agents rewrite this codebase with zero automated tests — and the iterate-until-green loop is exactly what agents are best at. Pick a runner.
Parent-Child Nested Organizations Are Not Modeled — Initiatives, Funds, and Sub-Orgs Have Nowhere Canonical to Hang
`upmobility-foundation-urban-institute` welds a parent org to its initiative, so triaged content has no honest folder to land in.
Refactoring for API Speed — a single-user app should boot in milliseconds, not a minute
Measured: shell mount to workspaces ready is ~543ms. The perceived minute was a stale deploy plus remotes hanging on `localhost:3XXX`.
Search & Add's invokes never reach the workspace — the pane hangs at 'searching…' while every backend rung is green
SearXNG answers, `search.fire` answers, the org card loads — yet the 🔍 pane hangs forever. The frame dies inside the client transport.
Session expiry turns the app into a zombie — the 12h JWT dies mid-use, the UI stays up, and every invoke times out
The `didi_session` cookie lives 30 days, the JWT inside ~12h, and nothing calls `/api/session/refresh` — the transport 4401-loops at 2/sec.
Tag input swallows commas into one mega-tag — commas should split into separate tags
`toDashed` splits on every non-alphanumeric, so commas behave like spaces and three intended tags fuse into one mega-tag.
Troubleshooting workspace ↔ DB state alignment — humain-vc's corpora don't load, and the canonical layer holds fewer than the operator created
The humain-vc workspace renders empty-or-wrong corpora while the canonical layer itself holds fewer humain-vc domains than the operator remembers creating — four suspects, each with a discriminating signature.
Workspace + corpora connection is slow-to-hanging, and the auth token won't persist
The Corpora Curator sits at 'connecting…' and the workspace switcher at 'loading…' — corpora never arrive — while the didi session drops within a minute of signing in, forcing a re-login. Two symptoms that most likely share one root cause.
Funder↔strategy is tags for now — whether it deserves a real edge is deferred
140 strategy tags landed on 69 funders, but a tag can't carry evidence counts, gift sizes, or recency. The edge question comes due later.
Header polish — the FLOW label and shell suffix have outlived their jobs, and the chat toggle sits on the wrong side
Four findings from the first production walk-through — including a chat toggle on the right that opens a rail pinned to the left.
Relation kinds are inverse pairs — one stored string can't speak from both seats
NextLadder is funded_by Ballmer Group; Ballmer Group is funder_of NextLadder — the same edge needs a different kind string per perspective, and today only one pair is special-cased in a read-time map.
Capability Gaps Surfaced by the First Triage Co-Pilot Run — One Collective Ledger, Not Five Tickets
Five gaps from the first triage run — including direct SurrealDB writes whose string-typed ids silently failed to join their org rows.
Corpus adds don't fetch metadata — and the row gives no cue either way, and there's no inspector to see or fix it
`organization.corpus.add` writes url, kind, and domain then stops — the Jina metadata fetch never fires, and nothing on the row says so.
Corpus items aren't visible on person cards — and corpus coverage across entities is hard to assess anywhere
The person card says 'Corpus items 3' and shows nothing — the operator can add a fourth without ever seeing the three that exist.
Crawl progress is a black box — 'crawling the web, this takes a minute…' needs traces the operator can watch
The model narrates as it crawls — `extractText` skips straight past it to the final answer, so the operator gets a minute of ellipsis.
Crawl replies can be lost — the eternal 'crawling…' spinner (no client timeout, reconnect-dropped invokes, tight dispatch ceiling)
The Curry Foundation crawl finished in 87s and the tab spun forever: no client deadline, reconnect-dropped invokes, a 300s ceiling.
The crawl's search substrate is fixed to Anthropic web search — the operator expected to choose
The manual 🔍 has a provider palette; `organization.crawl` is hardwired to Anthropic's server-side web_search with no dial and no label.
Switching flows from the Flows popdown doesn't surface the new flow's stage — a rotation-step click is required
Switching flows flips the pill but leaves the stage blank until a step-bubble click. Only tabs with persisted layout state reproduce it.
Invokes survive reconnects — the claim protocol closes the eternal-spinner root cause
Two crawls finished server-side while the tab spun forever. Pending invokes now survive a socket drop and re-attach by id via claim frames.
List rows show hostname only — the path is hidden, so same-domain entries are indistinguishable
`AdditiveList`'s `host()` drops the pathname, so two Gates Foundation links both render as `gatesfoundation.org` and can't be told apart.
Live/not-live indicator tooling — parts of the UI feel dead, and there's no single view that says whether everything is actually working
Five distinct failures — dead remote, dead socket, dead service, no refresh, unwired button — all present to the operator as one dead click.
Merging organizations or people — when two objects turn out to be the same entity, dedupe non-destructively
Two rows are sometimes the same entity and nothing merges them — no edge re-pointing, no list union, no slug absorbed into `aliases[]`.
No component library — the UI is improvised per-remote instead of component-based, and it's starting to show
Fourteen remotes improvised their own UI, so status pills and candidate pickers now exist in parallel dialects. The bill is arriving.
No user visibility into state — the app needs a State-Inspector surface
State lives in five places and none are inspectable from inside the app — nothing shows which remote currently believes what.
Org Workbench in a narrow pane — the roster doesn't collapse, and the org card's contents spill out of their container
In a narrow pane the roster keeps its 300px and the card's link rows overflow — the flexbox `min-width: auto` trap, twice.
The Org Workbench can't create an organization — and creation must sit behind a 'be sure there is no match' gate
The workbench can only find orgs that exist. Creation must sit behind the same show-every-match gate that already governs adding a person.
A person's bio page on another org's site is an affiliation signal, not just an identity link — the UI should offer the promotion
A bio on another org's domain is three facts — identity link, affiliation evidence, observation. The card captures one and drops two.
Pulse streams need an editable kind and a user-facing name — 'Today's Credentials' is not an 'updates_index'
The operator can neither fix a stream's inferred kind nor record its name — `media_streams[]` has no title field for Today's Credentials.
The search column holds stale results — a new agent search doesn't reload it
The team crawl bypasses the Search & Add envelope, so the column sits frozen on the last search's candidates, masquerading as current.
Team-crawl accept drops the crawled links and leaves the staged row — double-save risk
`person.apply` writes `linkedin_profile_url` as a scalar only, so accept discards the crawl's links — and the staged row lingers.
Search Providers as First-Class — Stand Up SearXNG as the New Default for Social Packs; Tavily Stays as a Peer; Per-Row Iteration as the Workflow We're Building Toward
Tavily is a content-RAG index — wrong substrate for social-profile pages. The fix isn't a swap — it's making provider plural per-fire.
Issue: How People, Organizations, and Their Relationships Actually Enter SurrealDB
Not a bug — a verified trace of the canonical write path, because the DB already does more than the UI or the operator's memory shows.
Issue: Person · DB Resolver UI needs to accommodate multiple organizations per person
`person-db-resolver` resolves one org per row, but Lincoln Ellis's bio names four — no way to add an Nth without re-running the row.
Grilling on the DB Resolver — questions to settle before v0.0.0.2 / v0.0.0.3
Three decisions before v0.0.0.2: where the join key lives, whether a slug can be renamed safely, and whether opportunities reopens Decile.
Personal-link observations need named query lenses — without them, an accumulating fact log goes uninspected
`has_personal_link` observations carry rich qualifiers and no queries. One thought leader can contribute 50+ before anyone can look.
Some records show empty corpus in the Sort & Filter Lens despite per-funder directories existing on disk — the lineage join is healthy but the workspace-service capability has no timeout override (defaults to 5000ms), the content-ingest handler processes requests serially, and each call walks every funder directory under clients/<id>/corpus/, so late requests in the 96-row fan-out time out and the lens swallows the error silently; the durable fix is to make corpus_funder_slug (a column the records sheet already populates) the primary join key, which limits each call to one small directory and dissolves the timeout race — this supersedes the originally-proposed corpus-overrides.yaml because the override surface is now the records-sheet cell
No `CAPABILITY_TIMEOUTS_MS` entry for `corpus.list_for_record` — 96 parallel calls hit the 5000ms default and the lens swallows the error.
Funder Corpus First Session Failed — 75 markdown files across 15 of 96 funders, 81 records unprocessable, hours spent layering filters on stale data instead of producing clean fresh data, rebuild against the goals spec exists in code but was never validated against a real pack fire because the session ended
Six hours produced 75 corpus files across 15 of 96 funders — 81 records still have nothing. This is the failure-mode list for morning-self.
OfficialPulse URLs Appear as Junk in Promoted Versions — operator believes promote v6 → v7 → v8 wrote bad data into the array column; audit shows promote is clean and v6 itself already contained every URL
Promote added nothing — v5 through v8 carry identical 122-URL arrays. The new renderer just made them visible, and no UI can remove one.
Augment Transformations Not Reliably Persisting — Hand-Curated Field Edits and Whole-Row Augmentations Are Disappearing Across Record-Set Versions
98 hand-curated URLs across 45 records with no save or promote affordance — only the row-store's auto-persisted JSON keeps them alive.
Troubleshooting UI for Official Blogs — The Bundle Fire Path Doesn't Fit the Flow That Was Built for Prompt Templates
Bundles fire end-to-end, but the Flow assumes every fire routes through a prompt template — so every step past 2 is wrong for a bundle.
Changelog entries duplicated across augment-it/changelog/ and content/changelog--laerdal/
Eleven backfilled augment-it changelog entries currently live in two places. Either location can be the source of truth — but right now both are, and updates have to be made twice.
general
agent-skills
blueprints
Augment-It as Working App and Architecture Demonstration
Augment-it is a working product and a live architecture showcase at once; every decision answers to both lenses so neither quietly wins.
Webhook as Wake-Up, Not as Truth — relaying platform events into CI without trusting them
Polling gets throttled and push payloads are unsigned. Forward the interrupt, not the claim, and both problems stop mattering at once.
Connecting To And Using SurrealDB
The one place that codifies how augment-it talks to SurrealDB Cloud — the five env vars, the connect → signin → use dance, the client-tagging write contract, and the dev-only-credentials posture that a proxy service eventually replaces.
Response–Row Identity Across Promote — Why Responses Outlive Their Rows, and the `record_uuid`-on-Response Fix
Promote deletes parent rows, leaving responses pointed at dead `row_id`s; carrying `record_uuid` on the response resolves them by identity.
Packs and Bundles — The Two-Tier Pattern for Entity-Profile Augmentation (and Beyond)
Two tiers: a pack is one source, one remote, one schema; a bundle is a named composition of packs fired by a single chat verb.
Original and Enhanced Record Instances — the Record-Instance Model
No mutation, no derived set per run: one immutable original plus one mutable enhanced instance per round, promoted to seed the next.
Module Federation + Rsbuild — Dev Loop Gotchas
Five Rsbuild + Module Federation gotchas, cross-origin HMR first: none block adoption, all cost time if you don't see them coming.
Spec-Kit and Context-V Coexistence — How They Work Together in Augment-It
context-v holds the project's living memory; spec-kit drives per-feature implementation flow. Complementary, not competing.
Why Response Reviewer and Highlight Collector Exist — The Verbose-Prose-to-Tabular Bridge
CRM cells are terse and LLM answers are prose; no structured-output regime removes the human integrity check that bridges them.
decisions
loops
Adopt Selector in one member
The test comes before the refactor. This is the first organ whose defects are invisible — a broken keyboard renders perfectly.
Adopt CardRow and a SelectWrapper in one member
The pilot executor. Three members answer the open decisions with evidence; everything mechanical is inherited from the Button loop.
Adopt the shared Button in one member — the per-member executor for the Button rollout
One member per run, never a sweep. Replace the buttons, delete the recipes they made redundant, raise everything else.
Adopt the shared Chip in one member
The per-member executor for the Chip rollout. Inherits every probe and verification rule from the Button loop; what differs is the judgement about what a chip even is.
Converge the federated design system — scan members for organs, fingerprint them, and triage divergence into five verdicts
Creativity is the default and stays the default. The loop's job is to notice when two teams solved the same problem twice without meaning to.
Endow a Component With Its Own Contracts
The repeatable procedure for giving one unit — service, remote, package, or shell — the four firsts it owes. One unit per run, never a sweep.
From a Raised Issue to Fixed-and-Shipped — the bug-to-ship loop
A raised issue becomes a context-v issue doc, a gh issue, then an attempt→verify cycle that safety-commits every failed try and milestone-commits the win — closing with a changelog beat and an offer to bump semver + tag.
Sweep — Local & Federated Design System for Fidelity
The repeatable procedure for checking a member's CSS against the federal contract. The one sanctioned exception to the two-file rule.
Implement-Feature Loop — plan → gh tickets → code/verify/changelog/commit per ticket → human browser test → ship
The generic feature-execution cadence: a signed-off plan becomes gh tickets, each ticket lands as verified code + a changelog beat + a conventions-clean commit, and the run closes with a human browser test and a ship() commit.
Loop through a spec — write the plan, implement, test, changelog, commit, repeat until Shipped
The phase loop that took Augment-From-DB-Flow from Signed-Off to Shipped in one day: plan, implement, prove, changelog, commit — per phase.
notes
Sharing code without breaking microfrontend autonomy: build-time import IS the copy
With no `shared` block, a workspace import is inlined into all seventeen bundles. The cost isn't runtime coupling, it's redeploy fan-out.
Why this monorepo does not need Turbo: a task graph with no edges
Turbo's core directive is `dependsOn: ["^build"]` — build my dependencies first. No package in packages/ has a build step, so it resolves to nothing. We adopted a best practice for an architecture we then didn't build.
The four layers: pnpm, Turbo, rsbuild Module Federation, and where Bun would fit
There isn't one 'monorepo' system — there are four independent ones, and the word 'federation' means two different things across them. Untangling which tool owns which job, and what Bun would actually replace.
Two tiers: WebSocket to the gateway, NATS between services
The browser talks WebSocket to one gateway; the gateway talks NATS to every service. They aren't alternatives — they're two legs of one design, and the gateway between them is where tenancy lives.
patterns
plans
Build Selector and close the keyboard contract
Nine surfaces declare a keyboard widget. Zero implement one. This is the first component whose whole substance is behaviour, so it is the first one with real tests.
Give the services a shared tsconfig base — fold ten byte-identical service configs onto a new `tsconfig.services.json`, reconcile `decile-mcp`'s real delta, fold two duplicated package configs onto the existing `tsconfig.base.json`, and correct the root fallback's stale exclude list
Ten service tsconfigs are byte-identical and extend nothing. The fix already exists one directory away — `tsconfig.base.json` did this for the apps and works.
Prove the component API end-to-end on request-reviewer — ship the scales, build Button, migrate one member, and verify by measurement
If this loop closes once it closes eighteen more times. One member, nine buttons, and a measurable accessibility delta.
Tidy every consumer onto the shared primitives
Button is done across nineteen units. This sequences what is left: Chip everywhere, the stale annotations, and the three containment jobs that are not component work at all.
Component-Level Documentation Contracts — Giving All Forty Units Their Own Four Firsts
Forty deployable units, fourteen READMEs, zero DESIGN.md files. The contract set each kind of unit owes, and the order to pay it down in.
Graphify as Standing Practice and Per-Component Diagrams — Visual Engineering That Doesn't Go Stale
The graph ran once, on 2026-08-06, and still names an app that was renamed two days later. Turning a snapshot into an instrument, and giving each unit its own picture.
Pickup notes — 2026-09-12: the watchdog got fixed, and so did the bug it was never going to catch
A "Twenty is broken" report that wasn't, a production bug that only appears on a dead socket, and three days of infrastructure that lives outside git.
Stale Corpus Sources When the Workspace Socket Is Down — the header moves, the list doesn't
Switching corpora on a dead socket silently shows another corpus's sources under the new name — a wrong answer wearing a confident label.
Back Up the Content-Ingest Corpus Volume — the corpus has no second copy
Every fetch writes to a single Railway volume that nothing backs up, nothing mirrors, and only one process can even read.
Fix Env Aliasing That Drops PUBLIC_ Vars in the Developers Menu
Assigning import.meta.env to a variable defeats rsbuild's static replacement, so two production URLs quietly resolve to localhost.
Re-Mint the Deploy-Watch Railway Token — the watchdog has been blind for days
The watchdog built so a failed deploy would not go unnoticed for twelve days has never once run green itself.
Test coverage — pick the harness, seed the suite from the prove-scripts, and loop the open bugs to green
Vitest + Playwright for this repo, ExUnit already standing in id-didi-sh — convert the six prove-scripts into a permanent suite, then write the humain-vc corpora bugs as failing tests and iterate until they pass.
Open augment.didi.sh to reach-edu — a second tenant instance, and Stephenie Tesoro as the first client user
The data is already deployed; only the door is single-tenant. Open it with a per-client instance, not a relaxed org check.
CRM Starter Export — the pipeline shape, enriched from the canonical layer: orgs first, then people attached
Two CSVs seed the empty CRM from the canonical layer: organizations first, people second, attached by a stable key. Corpora excluded.
Org Relations (parent/child/peer) + Org Tags — model, capabilities, and the Org Workbench surface
Organizations finally get edges to each other — parent, child, or peer, with a typed flavor and free-text human context — plus their first tag mechanism (Initiative, Program, Funder), all workable from the Org Workbench card.
Didi crawl — three targets (links, streams, team members), the relevance brief, and staged team ingest
One `organization.crawl` capability over Anthropic's server-side web_search, driven by a per-workspace, operator-editable relevance brief.
Workbench usability sweep — corpus visibility, stream editing, and promote-to-affiliation (issues #20 · #26 · #25)
Today's scope from the first real workbench session: make the person card's three invisible corpus items visible, let the operator fix a stream's kind and give it its real name, and turn a bio-page link row into a three-click affiliation.
Workspace-scope legibility — empty workspaces and stale org restores should explain themselves, not look broken
Switching to a workspace with 0 orgs made the workbench look dead — the visibility rules were right, only the messaging failed.
Augment from DB · Phase 1 — service capabilities + Exa, no UI
Four service-side deliverables that make the whole flow provable from a script before any remote exists: org detail + org affiliations reads, a registry-resolved search.fire, and Exa as a peer connector.
Augment from DB · Phase 2 — the org-workbench remote: flow registration, org search, org card
Autocomplete to a canonical org and work its card with a live ➕ on every list — plus the verb the spec missed, `organization.streams.add`.
Augment from DB · Phase 3 — the search-and-add remote: editable term, provider palette, one-click add
Launched from any 🔍 on the org card: an always-editable term bar, a provider palette, one-click add back to the launching list.
Augment from DB · Phase 4 — people reveal, person cards, add-person with automatic affiliation
The org card grows its people: every affiliated person revealed with role + relevance, nested identity links with their own ➕ and 🔍, and an inline add-person where the affiliation edge materializes without the operator ever managing it.
Augment from DB · Phase 5 — stream-scan mode: scan a pulse stream, badge the already-known, one-click the new into the corpus
Stream scan is a mode of search-and-add, not a third remote: the stream URL is the authoritative index, deduped against `content_items`.
Plan stub: ingest the next reach-edu event CSV into the canonical layer
The mechanism already exists and is proven twice over (turning-jobs, FreedomFest) — this is the sequence to run the moment the next event CSV lands, so it's 'follow the stub' instead of 're-derive the pipeline.'
Pickup notes — 2026-07-13: deploy hardening, doc audits, credential hygiene
Steps 1–10 are live at augment.didi.sh; this session cleared the production-only bugs that only using the deployed app surfaced.
Build order: the humain-vc unlock flow, step by step
The execution sequence for Flow 1 — each step names its repo, files, and verification, so a fresh session can pick up mid-sequence.
Person-aware canonical resolver — closing the gap between the proven scripts and the shell-reachable capability
The resolver only knows organizations; every person and affiliation ever written came from CLI scripts no UI can reach.
SurrealDB MCP + a verification skill — querying augment-it's canonical layer directly, starting with FreedomFest 2026
Migrate off the deprecated `nats` package to the `@nats-io/*` scoped v3 client — swap `nats@2` for `@nats-io/transport-node@3` across all 10 services, drop the removed `JSONCodec` in favor of `JSON.stringify` + `msg.json()`, and prove the inter-service bus still round-trips live before committing
`nats` → `@nats-io/transport-node` v3 across 27 files: mechanical, except the removed `JSONCodec` rewrites every encode and decode.
First-Pass Corpus Quality Scan for reach-edu — a measured before/after baseline of the RAG corpus
A read-only baseline of 517 markdown files across 57 funder dirs, taken before RAG is wired, so 'after' has a 'before' to compare to.
Canonical Entity Registry on SurrealDB Cloud — just write records
SurrealDB Cloud is up at main/main with three SCHEMALESS tables (persons, organizations, affiliations). Goal: write records from tonight's CSV+JSONL into those tables. SCHEMALESS stays. No field discipline up front.
Augmentation-state preservation and snapshot promotion — the operator's CSV is the system of record, the filesystem is the truth, and `/promote-snapshot` is the verb that walks the corpus and emits the next CSV with system columns appended so flow-switches don't erase the prior cycle's work
One verb: `/promote-snapshot` joins the corpus filesystem into a fresh CSV version with system columns. No register, no write-hooks.
Download PDFs into Corpus Inbox — preserve the original binary alongside Jina-extracted markdown; wire both inbox vectors (UI and agent-chat) so the operator's PDF discoveries land as commit-able evidence, not just summarized text
Jina gives the inbox text and throws the PDF away — nothing to cite by page or hand to a co-researcher. Save the binary alongside it.
URL Auto-Detector and Clickable Rendering for List Fields — make socials, helpful_links, and official_updates_index_urls open-in-tab links instead of opaque JSON
`socials` and its list-shaped siblings render as 12px JSON; a shape-detecting extractor makes every URL clickable and drops the clutter.
In-App Chat v0.0.1 for Augment-It — The Prompt-Drafting Triad as the Demo Affordance
Gated enhancement made conversational: `prompts.draft` → `improve` → `apply`, with postconditions that check what the prompt promised.
Shell & Micro-Frontend UX Coherence — Refactor Plan
Eight locked UX decisions sequenced into five phases — the Deck→Flow rename first, so every later phase speaks the right vocabulary.
Augment-It Workspace — Walking Skeleton Plan
Browser ↔ Workspace Service over WebSocket, Workspace Service ↔ row-store over NATS, and two real spreadsheets as the proof-of-life payload.
Impose the Three-Mode Theme System on augment-it
The two-tier tokens and light/dark/vibrant contract adapted to a federated, Tailwind-less app: one shared `packages/theme`, no raw hex.
Prompt-Template-Manager — Walking Skeleton Plan
Author `{{column}}` templates and run them per row — `prompt-runner` is the only container that calls the Anthropic API.
Run-as-First-Class-Operation — Pair Pack-Runner with Prompt-Template-Manager, Make Runs Legible Across the Pipeline
Lift `Run` from a string id buried on each response into a real entity, so any surface can see which batch produced what it's showing.
refactors
The federal layer never shipped --space-*, --radius-* or --z-* — so ten members invented token names and let the fallback carry the value
170 declarations across the federation reference tokens that do not exist. Each one silently ships its literal in all three modes.
sort-filter-lens leaks 61 unnamespaced classes into every other remote — and .error, .row and .muted are live collisions today
One member ships 511 lines of global CSS with no root-class containment. Sixteen other surfaces render a class it restyles.
Two palette steps share one hex, so dark-mode borders measure 1.00:1
graphite-700 and graphite-800 are both #232634. Four federal boundary findings came out of one member's probe; three survive adjudication and one does not.
Rename the corpora curator — finishing a rename that only ever reached the label
Four naming layers were tangled here and only three moved — the fourth is a data value living in two external client repos.
Structural refactors surfaced by the codebase graph — the deadweight, the boilerplate, and the CSS convergence problem
A zero-token graph over 490 files found ~500 lines that delete cleanly, 11 near-identical `mount.ts` files, and no duplicate CSS after all.