← Corpus / augment-it / exploration

augment-it has outgrown one flow — ROTATION is the CSV-augmentation pipeline's shape wearing a general-purpose name, and strategy-curator's promotion to its head is a splice, not a fit

augment-it started as one thing — augment a CSV, row by row — and ROTATION (shell/src/remotes.ts) is that flow's shape, hardcoded as THE numbered nav. Every use case since (DB-canonicalization for reach-edu's CRM exit, per-org/person corpus curation, now domain/thesis curation for humain-vc) has been reconciled onto that one array instead of recognized as its own flow. Strategy Curator's 2026-07-06 'promotion to the head of ROTATION' is the symptom: a domain-curation session doesn't hand off into recordCollector, but ROTATION was the only navigation primitive that existed, so that's where it landed. The fix isn't a bigger ROTATION array — it's a 'what are you trying to do?' front door that picks which flow mounts, so a use case that isn't CSV-row augmentation stops being forced to pretend it is.

Path
explorations/Augment-It-Has-Outgrown-One-Flow-The-Choose-A-Flow-Front-Door.md
Authors
Michael Staton
Augmented with
Claude Code on Claude Sonnet 5
Tags
Exploration · Augment-It · Shell · Rotation · Flow · Strategy-Curator · Thesis-Curator · Record-DB-Resolver · Workspaces · Humain-VC · Multi-Flow · Front-Door · UX-Architecture

augment-it has outgrown one flow

The observation — why this exists

2026-07-06, mid-session: after wiring didi.sh actor attribution end to end, the operator opened http://localhost:3017 expecting to see the strategy-curator in context (auth badge, workspace switcher) and instead saw the bare remote — no chrome, because :3017 is apps/strategy-curator’s own standalone rsbuild dev server, not the shell. The proximate fix is trivial: go to :3100 instead. But the operator’s actual point, in their own words:

“The standard augment-it flow doesn’t have the corpus curator. It’s an app we made to plug a hole. It is very handy though. We also kept running into workflows that don’t fit the current shared shell header of 1-2-3-4.”

That’s not a bug report. It’s a description of an architecture that has quietly forked into multiple flows while the shell still presents exactly one numbered sequence.

How we got here — the actual history

Reconstructed from the operator’s account plus the git/context-v trail:

  1. CSV augmentation (the original, proven flow). Upload a CSV, author prompts, run them per row, triage responses, promote a snapshot. This is recordCollector → promptTemplateManager → requestReviewer → responseReviewer in spirit — today’s ROTATION minus the parts added later. It works. It shipped first because it was the whole product at first.
  2. An event CSV needed dynamic person↔org iteration. reach-edu wanted off their CRM entirely, so the natural move was to write canonical records to SurrealDB directly — with CRM-specific and client-specific flags — rather than bolt a migration script onto the side. This is record-db-resolver (spec: [[../specs/Record-DB-Resolver]]): match-or-create against canonical organizations/persons, additive, one row at a time. It got folded into ROTATION as step 3 (recordDbResolver — “bridge — reconcile records to canonical orgs”) — a reasonable fit, because it still operates per-CSV-row.
  3. Organizations and some individuals warranted their own corpora — links and downloads gathered independent of any one CSV row. This is where content-ingest, the sources/source_usages/domains SurrealDB tables, and the whole corpus-curation substrate ([[../specs/Funder-Content-Corpus-Workflow]]) came from. Still record-adjacent at this point — corpus entries hung off record_id.
  4. reach-edu needed corpora for “strategies” — cases to support or flesh out potential fundraise directions, decoupled from any single CSV row. This is strategy-curator ([[../specs/Strategy-Curator-Entry-Point-for-Augment-It]]): pick a domain (type=‘strategy’), gather sources against IT, not against a record. This is the fork. The unit of work stopped being a record row and became a domain. strategy-curator had no natural slot in ROTATION — it isn’t a step in the CSV pipeline, it’s the entry point to a different pipeline — so it shipped as a standalone remote, reachable only by its own dev port.
  5. humain-vc now wants the identical shape for “theses” — corpora that will become decks via dididecks-ai downstream. This is Build-Order step 5 ([[../plans/Build-Order-Humain-VC-Unlock-Flow]]): make the curator’s domain_type workspace-derived instead of hardcoded 'strategy', so humain-vc reads “Thesis” and reach-edu keeps “Strategy.” Same app, second client, second domain-type — proof the domain-curation flow is now a first-class citizen, not a one-off.
  6. 2026-07-06: strategy-curator promoted to the head of ROTATION (commit 1d4acc0, shell/src/remotes.ts:34-42, +4/-2 lines). This gave the curator a reachable, chrome-having entry point for the first time — genuinely useful, unblocks Flow 1’s “primary surface” framing in the Build-Order plan. But look at what the diff actually did: it spliced a domain-curation entry point onto the front of an array whose remaining six members (recordCollectorrecordDbResolveraugmentrecordsSurfaceresponseReviewerenhancedRecordsList) are all CSV-row-augmentation steps. Nothing in strategy-curator hands off into recordCollector. The “numbered flow” is now a lie for one out of seven steps — you don’t walk from Strategy Curator into Record Collector as part of one continuous task.

The actual architectural collision

ROTATION (shell/src/remotes.ts:34-42) is one hardcoded array. It is simultaneously trying to be:

  • The CSV-row-augmentation pipeline’s step order (its original and still-true shape for 6 of 7 members).
  • THE numbered navigation for the whole shell (its assumed role — every new capability gets a slot, because a slot is the only way to be reachable with chrome).

Those two roles were the same thing when augment-it did one thing. They aren’t anymore. Three distinct flows exist in the product today, and only one of them is what ROTATION actually models:

FlowUnit of workAppsIn ROTATION today?
A — CSV Row Augmentationone CSV rowrecordCollector, recordDbResolver, augment (PTM⇄PackRunner⇄SortFilterLens), recordsSurface, responseReviewer, enhancedRecordsListYes — this IS what ROTATION models
B — Canonical DB Reconciliationone person/orgrecordDbResolverEmbedded inside Flow A (step 3) — also directly useful standalone once reach-edu is fully off their CRM
C — Domain/Thesis Corpus Curationone domain (strategy or thesis)strategyCurator, content-ingest’s corpus tables, (soon) dididecks-ai downstreamSpliced onto Flow A’s front as step 1, despite sharing no data spine with steps 2-7

Flow C doesn’t key off record_uuid the way Flow A does — it keys off domain_type:domain_slug. There is no natural “next step” from Strategy Curator into Record Collector; an operator finishing a thesis-curation session doesn’t want to walk into CSV upload. The promotion made the curator reachable, which was worth doing, but it didn’t make it belong where it landed.

A second, smaller collision: three senses of “Flow”

Worth naming so a future session doesn’t conflate them (surfaced while researching this):

  1. Shell “Flow”ROTATION, the numbered nav sequence (FlowWidget.svelte, “Flow 1”, “Flow step 1” in code comments).
  2. Build-Order “Flow 1” — a whole user-journey for humain-vc: auth → workspace → thesis corpus, spanning both id-didi-sh and augment-it ([[../../context-v/plans/Unlock-Humain-VC-Team-Access-To-Augment-It]]).
  3. This exploration’s “flow” and the sibling exploration’s “operator-built flow” — a top-level use-case (this doc) or a verb-sequence-against-a-view (the sibling doc) — neither is the shell’s numbered nav.

Same word, three referents, three different docs. Not urgent to rename, but worth a one-line disambiguation wherever “Flow” appears without qualification.

Relationship to the sibling exploration

[[Operator-Built-Flows-Beyond-The-Universal-Pipeline]] is about the SAME underlying tension — “the universal pipeline is a dud outside its happy path” — but one layer down: it’s about customizing granularity within Flow A (which records, in what order, with what verbs). This exploration is one layer up: which flow is even active. They compose cleanly:

  • This doc’s “choose a flow” front door picks Flow A, B, or C.
  • Once Flow A is chosen, the sibling doc’s Tiers 1-4 (saved views → named playbooks → agent-composed view-specs → deferred flow-editor) apply inside Flow A, same as today.
  • Flow C (domain/thesis curation) might eventually want its own Tier-1-style saved views (“my open theses,” sorted by source count) — same pattern, different flow. Not scoped here; noted for later.

The design space — climb only as needed, same ethos as the sibling doc

Option 1 — Do nothing; keep splicing (status quo)

Every new use case gets folded into ROTATION wherever it fits best, or shipped standalone if it doesn’t fit at all. Cheapest, and it’s why strategy-curator exists and works today. Cost: ROTATION keeps meaning less as it grows (it’s already lying for 1 of 7 members); each new flow that doesn’t fit either gets awkwardly spliced in (repeat 2026-07-06’s move) or stays a standalone-port app operators have to remember, as happened today.

Revised after operator feedback: the original draft of this option proposed a pre-auth landing screen (sign in → pick a flow → mount). That’s the wrong shape for right now — with exactly two users (Michael, Aniel), gating flow-choice behind auth machinery is complexity with no payoff yet. The corrected, much lighter shape:

Use the existing “jumbo popdown” convention — a large, content-rich dropdown menu triggered from the header, documented at astro-knots/context-v/blueprints/Jumbotron-Popdown-Patterns.md and implemented (Astro) at astro-knots/sites/fullstack-vc/src/components/ui/menus/JumboPopdown__*.astro. Shape per that blueprint: a trigger button with a chevron (aria-haspopup="menu", aria-expanded), a panel (role="menu", hidden until opened, hover-open + click-toggle, Esc/click-outside closes) containing a grid of items — each item a title + one-line description, 6-8 items max. augment-it’s shell is Svelte, not Astro, so this is a pattern port (same interaction/visual contract, native Svelte implementation), not a shared dependency — consistent with the “no shared dependency across ai-labs apps” convention (patterns get copied/adapted per app, never imported as a package or microfrontend across dididecks-ai/augment-it/memopop-ai). The shell’s own WorkspaceSwitcher.svelte is the closest existing analog in augment-it today, but it’s a compact role="listbox" single-column dropdown — the jumbo variant is the richer, grid-based sibling for a menu that wants to say more than one line per item.

Scope for right now: exactly one entry. The popdown ships with a single item — “Build Corpora” — which mounts strategyCurator as its own focused surface (no CSV steps trailing behind it, same fix for today’s :3017 confusion as the original draft: the popdown becomes the on-ramp, replacing the memorized-port habit). ROTATION itself is untouched — it keeps mounting as the shell’s default/home state, exactly as today. No ActiveFlow persistence, no landing screen, no auth-gating: clicking “Build Corpora” is just a navigation action, same mechanism as any existing augment-it:navigate event to a non-rotation remote (chat, packRunner, personEnrichment already work this way).

The “helpful marketing” framing (operator’s words) is a real, but later, upgrade path. Once there’s more than one flow-entry worth surfacing, the popdown’s panel is the natural place for a richer showcase — a vertical carousel of use-cases, each with a short pitch, matching the blueprint’s “content-rich” intent rather than a bare link list. Not needed for a one-item menu; worth revisiting when a second or third “Build ___” entry exists (see Recommendation).

Why this is the right first move, not over-engineering: it’s a single new header component, no new global state, no backend changes, no interaction with Step 7’s (still-open) sign-in wall. ROTATION, FlowWidget, and the composite-slot mechanism are completely untouched.

Cost estimate: small. One Svelte component (JumboPopdown.svelte or similar, ported from the astro-knots blueprint’s interaction contract), wired into the shell header next to WorkspaceSwitcher/DidiBadge, one menu item, one navigate-to-strategyCurator action.

Option 3 — Let each flow be its own top-level shell (defer)

Spin up a second shell instance entirely for Flow C, federation-composed independently. Overkill today — one shell already composes remotes fine; the problem is navigation-model, not composition-model. Would only become worth it if Flow C’s UI needs (theme, layout grid, chat-rail behavior) diverge from Flow A’s, which they don’t yet.

Key considerations

  • recordDbResolver (Flow B) is genuinely dual-use, confirmed live — it’s step 2 of CSV_AUGMENTATION_ROTATION AND the whole point of EVENT_ATTENDEES_ROTATION (shipped 2026-07-07 as its own flow, “Augment a CSV of Event Attendees”). No collision: the same remote id in two different flows’ rotations resolves independently each time via slotById() — nothing shares state between the flows beyond the remote itself.
  • Workspace ≠ Flow. active_workspace_slug (which client — reach-edu vs humain-vc) is a persisted piece of state; which flow-entry the operator just clicked in the jumbo popdown is not (it’s a one-shot navigate, not a mode the shell remembers across reloads) — at least until there’s a reason to persist it. Keep the two conceptually separate even though only one of them is stateful today.
  • This directly un-blocks today’s confusion. The reason the operator went to :3017 is that there was no “curate a domain” on-ramp at :3100 to click instead. The popdown’s “Build Corpora” entry is that on-ramp; once it exists, the standalone-port habit has no reason to persist (the remote stays federation-registered and technically reachable standalone, same as chat/packRunner/personEnrichment today, but nobody needs to remember the port).
  • Doesn’t block Build-Order step 5. Making strategy-curator’s domain_type workspace-derived (humain-vc → thesis, reach-edu → strategy) is orthogonal to which flow-picker button reaches it, and should proceed regardless of when/whether Option 2 ships.
  • dididecks-ai as the eventual downstream of Flow C. Theses become decks. That hand-off (domain/thesis → deck generation) is itself a candidate future flow or a Flow-C exit action (“build a deck from this thesis”) — not scoped here, but the front-door framing should leave room for it rather than assume Flow C’s endpoint is just “more curated sources.”

Recommendation — sequence

  1. DONE 2026-07-07 (superseded the “cheap comment” framing below with the real thing). ROTATION is now CSV_AUGMENTATION_ROTATION + BUILD_CORPORA_ROTATION (shell/src/remotes.ts), each owned by a FlowDef in the new shell/src/flows.svelte.ts (FLOWS registry + an activeFlow singleton, same constructor-$state pattern as layout.svelte.ts). strategyCurator came back OUT of the CSV-augmentation rotation entirely — the 2026-07-06 splice is undone, not just relabeled.
  2. DONE 2026-07-06, then extended 2026-07-07 — the popdown is now a real flow switcher, not a one-item navigate action. Original scope (below) shipped 2026-07-06: shell/src/JumboPopdown.svelte + a single “Build Corpora” item. The next session pushed it to what this doc always pointed at: the popdown moved from the header’s right-side metrics into header-left, sitting where FlowWidget lives; its items are now generated from the FLOWS registry (both “Improve a CSV” and “Build Corpora”); FlowWidget.svelte takes rotation: string[] as a prop instead of importing a constant, so its bubble strip resizes to however many steps the active flow actually has ($derived, not a plain const); layout.svelte.ts’s focus-index clamping reads activeFlow.rotation.length instead of a fixed ROTATION.length. Picking a flow persists (localStorage, mirroring layout/workspace) and resets focus to step 1 while preserving layout mode — EXCEPT co-existence, which falls back to peek-flow, since PAIRINGS are tied to specific CSV-augmentation slot ids and don’t carry meaning across flows. Verified: svelte-check clean, compiled bundle confirmed serving activeFlowId/Improve a CSV/Build Corpora/CSV_AUGMENTATION_ROTATION, backend GATE re-checked (unaffected, shell-only change).
  3. DONE 2026-07-07 — Flow B got its own entry sooner than expected. The operator asked for it directly: “Augment a CSV of Event Attendees”EVENT_ATTENDEES_ROTATION (recordCollectorrecordDbResolver, 2 steps), one new FLOWS entry. Proved the “one array + one entry” cost claim in real time — shipped in minutes, no architecture change. recordDbResolver is now genuinely dual-use across two live flows (step 2 of “Improve a CSV,” and the whole point of this one), not embedded-and-dormant as this recommendation originally assumed.
  4. Still don’t build a general flow-editor, a config-driven flow registry loaded from disk, or a pre-auth landing experience. Two hardcoded FLOWS entries is exactly the “climb only as needed” ethos holding — adding a third flow is one array entry + one rotation array, not new architecture. Grow the popdown’s panel (the “helpful marketing” vertical-carousel framing) only when a third flow-entry actually shows up.

Open questions

  • Should the popdown grow a second item before or after Build-Order step 7’s sign-in wall lands? No dependency either way today (the popdown doesn’t touch auth), but worth a quick check-in once Step 7 ships in case the two end up wanting shared header real estate.
  • Is strategyCurator the right name once the popdown exists and humain-vc reads “Thesis”? The app id and remote label still say “Strategy Curator” everywhere; Build-Order step 5 handles the in-app copy but the code identifier will keep saying strategy. Fine to leave — renaming identifiers is friction without payoff — but worth a code comment noting the id is legacy-named once step 5 ships.
  • What does Flow C’s own “done for now” checkpoint look like? Flow A has enhancedRecordsList as its checkpoint step. Flow C has nothing analogous yet — probably fine until there’s more than one app in Flow C’s rotation.

See also

  • astro-knots/context-v/blueprints/Jumbotron-Popdown-Patterns.md — the “jumbo popdown” convention this doc’s Option 2 ports into augment-it’s Svelte shell (pattern port, not a shared dependency). Reference implementation: astro-knots/sites/fullstack-vc/src/components/ui/menus/JumboPopdown__*.astro.
  • [[Operator-Built-Flows-Beyond-The-Universal-Pipeline]] — the sibling exploration, one layer down (customizing granularity within a flow, not choosing which flow).
  • [[../specs/Strategy-Curator-Entry-Point-for-Augment-It]] — the spec of record for the Flow-C entry point this doc discusses; already self-titled “An Entry-Point App,” which this exploration takes at face value and argues should get a real front door rather than a ROTATION splice.
  • [[../specs/Record-DB-Resolver]] — Flow B’s spec; the “dual-use, embedded in Flow A today” app.
  • [[../specs/Workspaces-as-Tenant-Primitive]] — the sibling axis (active_workspace_slug) this doc’s flow-navigation is conceptually distinct from, even though the popdown itself carries no persisted state.
  • [[../plans/Build-Order-Humain-VC-Unlock-Flow]] — step 5 (thesis vocabulary) proceeds independently of this exploration; step 7 (sign-in wall) has no hard dependency on the popdown either way.
  • [[../../context-v/plans/Unlock-Humain-VC-Team-Access-To-Augment-It]] — where “Flow 1” names the whole humain-vc user-journey, the second sense of “Flow” this doc disambiguates from the shell’s ROTATION.
  • [[../../context-v/explorations/Two-Clients-One-Flow-Corpora-Auth-and-Deployment-Converge]] — the ai-labs-level strategic framing this doc’s Flow C is the tactical, shell-navigation-level version of; its Thread 1 (“domain-type becomes operator-facing”) is exactly Build-Order step 5, which this doc treats as proceeding independently of the front-door question.
  • 2026-07-06, mid-session — the operator opened :3017 expecting shell chrome, found none, and named the underlying gap in their own words: “we kept running into workflows that don’t fit the current shared shell header of 1-2-3-4.” That’s the origin of this doc.