|
2 | 2 | title: "Augment from DB — the Org Workbench + Search-and-Add flow: two new microfrontends over capabilities that mostly exist" |
3 | 3 | lede: "Start from a canonical organization instead of a CSV row: smart-search to an org, see everything the DB knows (links, streams, corpus, people), and augment any list through provider-pluggable search with a one-click add — two small remotes, four new capabilities, one new connector." |
4 | 4 | date_created: 2026-07-22 |
5 | | -date_modified: 2026-07-22 |
| 5 | +date_modified: 2026-07-24 |
6 | 6 | authors: |
7 | 7 | - Michael Staton |
8 | 8 | augmented_with: |
9 | 9 | - Claude Code on Claude Fable 5 |
10 | | -semantic_version: 0.1.0.0 |
| 10 | +semantic_version: 0.1.1.0 |
11 | 11 | date_first_published: 2026-07-22 |
12 | 12 | exploration_of_record: "[[../explorations/Augment-From-DB-Flow-Two-New-Microfrontends]]" |
13 | 13 | post_ship_note: "All five phases implemented, proven, and pushed on 2026-07-22 (attempt(augment-from-db, …, step1–5)). Pending: the operator browser walk-throughs each phase plan names, and the parked open questions (fire-log persistence, pack-template seed terms, pinned-deploy env-configurable remote URLs). Deviations from the as-specced snippets are recorded in each phase plan's post_ship_note — notably organization.streams.add (a verb the spec missed), the localStorage-hardened D2 launch contract, and relevance as string|null." |
14 | 14 | revisions: |
| 15 | + - "2026-07-24 — v0.1.1.0: §v1.2 extensions added — the coverage roster recorded as shipped (OrgRoster + organization.roster, gh #32, un-deferring #20's layer 2), and the didi agent-crawl capability specified: 'crawl for relevant identity links / pulse streams' as chat verb AND list button (one implementation, two triggers), candidates-into-state never direct writes, driven by a per-workspace operator-editable relevance brief. Plan pending; composes with the didi-chat team-page plan." |
15 | 16 | - "2026-07-22 — v0.1.0.0: status → Shipped. Phases 2–5 executed same day ([[../plans/Augment-From-DB-Phase-2-Org-Workbench-Remote]], [[../plans/Augment-From-DB-Phase-3-Search-And-Add-Remote]], [[../plans/Augment-From-DB-Phase-4-People-Reveal-And-Add-Person]], [[../plans/Augment-From-DB-Phase-5-Stream-Scan-Mode]]; changelog 2026-07-22_02 through _05). Both remotes live (:3014, :3016); stream-scan flip-test proven against Aspen's blog." |
16 | 17 | - "2026-07-22 — v0.0.1.1: status → Implementing. Phase 1 executed and shipped same day ([[../plans/Augment-From-DB-Phase-1-Service-Capabilities]], changelog 2026-07-22_01) — all four capabilities live and proven over NATS; both flagged SurrealQL constructs worked without fallbacks. Phases 2–5 remain." |
17 | 18 | - "2026-07-22 — v0.0.1.0: user sign-off. Narrative pass ran clean — the doc was written in one pass after the exploration settled, so structure and prose stand as drafted; no TBD markers existed. Next step per the spec→plan cascade: cut Phase 1 as the first plan in context-v/plans/." |
|
29 | 30 | - Exa |
30 | 31 | - Pulse-Streams |
31 | 32 | - Affiliations |
| 33 | + - Didi-Chat |
| 34 | + - Coverage |
32 | 35 | status: Shipped |
33 | 36 | --- |
34 | 37 |
|
@@ -569,6 +572,94 @@ Each phase becomes (or is treated as) a plan in `context-v/plans/`, per the spec |
569 | 572 | **Success criteria:** scanning a known blog_index stream returns items with correct `already_in_corpus` flags; adding one flips its badge on re-scan; scanning the same stream twice adds nothing without operator clicks. |
570 | 573 | **Risk:** medium-high on social walls (accepted, experimental), low on blog/RSS. |
571 | 574 |
|
| 575 | +## v1.2 extensions — the roster front-column (shipped) and agent-crawl with an editable relevance brief (specified) |
| 576 | + |
| 577 | +Two same-day extensions the first real workbench sessions demanded |
| 578 | +(2026-07-24). The first is already live and recorded here so the spec stays |
| 579 | +the source of truth; the second is specified here ahead of its plan. |
| 580 | + |
| 581 | +### The coverage roster — the column in front of the flow (SHIPPED 2026-07-24) |
| 582 | + |
| 583 | +The flow's original first move was the search box, which presumes the |
| 584 | +operator knows which org to work. The real first question is usually |
| 585 | +**"which orgs could and should have more corpus content?"** — so an |
| 586 | +`OrgRoster` column now fronts the flow: every org the workspace client can |
| 587 | +see (`client_access CONTAINS` the active client — the default filter IS the |
| 588 | +workspace), name/slug-filterable, sorted by corpus count ascending (toggle), |
| 589 | +zero-corpus in red, rows carrying `corpus · links · streams · people` |
| 590 | +counts, click → the card. One new read (`organization.roster` — counts via |
| 591 | +`array::len` + `count(<-affiliations)`, no arrays on the wire). gh #32, |
| 592 | +changelog `2026-07-24_05`; workspace-scope legibility follow-ups live in |
| 593 | +[[../plans/Workspace-Scope-Legibility-Empty-Workspace-And-Stale-Restore-Handling]]. |
| 594 | + |
| 595 | +### Didi in the workbench — "crawl for relevant X", chat verb AND button |
| 596 | + |
| 597 | +The workbench gains agent actions, arriving through two equivalent doors: |
| 598 | + |
| 599 | +- **Chat**: the didi rail (integration owned by |
| 600 | + [[../plans/Didi-Chat-In-Org-Workbench-Verify-Team-Page-Into-People-Objects]]) |
| 601 | + understands *"crawl for relevant identity links"* and *"crawl for relevant |
| 602 | + pulse streams"* against the org in view. |
| 603 | +- **Button**: a `crawl` action on the org card's links and streams lists |
| 604 | + fires the identical capability with zero typing — the chat verb and the |
| 605 | + button are one implementation with two triggers. |
| 606 | + |
| 607 | +**Why an agent, why now:** identity links and pulse streams are exactly the |
| 608 | +shape web-search-equipped agents get mostly right, quickly — "official site, |
| 609 | +LinkedIn, X, YouTube, blog/newsroom index for ‹org›" is a solved retrieval |
| 610 | +problem. The expectation is the agent fills most of a thin org's lists in |
| 611 | +one crawl; the per-row accept gate exists for the tail (wrong org with a |
| 612 | +similar name, dead links, fan pages), not the norm. This inverts the manual |
| 613 | +🔍 flow's economics: the operator stops composing queries and starts |
| 614 | +adjudicating candidates. |
| 615 | + |
| 616 | +Behavior contract (both doors): |
| 617 | + |
| 618 | +1. The agent takes the org (name, domains, existing list entries) **plus the |
| 619 | + relevance brief** (below) and drives the existing search/crawl substrate |
| 620 | + (connector registry / packs — the manual 🔍 search-and-add's agentic |
| 621 | + sibling: search-and-add is operator-term-driven; crawl is agent-driven, |
| 622 | + multi-query, brief-informed). |
| 623 | +2. Results land as **candidates in state, never direct writes** — the same |
| 624 | + staged-objects gate the team-page plan establishes. The operator accepts |
| 625 | + per-row; accepts ride the existing verbs (`organization.links.add`, |
| 626 | + `organization.streams.add`). Dedupe against existing entries by URL |
| 627 | + before presenting (candidates the org already has are noise). |
| 628 | +3. Per [[Client-Tagging-on-Canonical-Writes]], accepted writes carry the |
| 629 | + client; the crawl itself is read-only against the world. |
| 630 | + |
| 631 | +### The relevance brief — editable context held in state |
| 632 | + |
| 633 | +"Relevant" is not inferable from the org row alone — it's the operator's |
| 634 | +standing intent (e.g., reach-edu cares about US higher-ed / workforce |
| 635 | +funders and their education-adjacent publication streams). The brief is: |
| 636 | + |
| 637 | +- **A small editable context document** — plain prose, owned by the |
| 638 | + operator, loaded into every crawl (and eventually every didi action in |
| 639 | + this workbench). First-class UI: view + edit in place (a panel off the |
| 640 | + workbench header; the State-Inspector issue's "what does the app |
| 641 | + believe" ethos applied to agent context). |
| 642 | +- **Scoped per workspace client** (reach-edu's brief ≠ humain-vc's), with |
| 643 | + per-org additions later if needed. |
| 644 | +- **Storage — open question**: localStorage is the v1 floor, but a brief |
| 645 | + the agent reads server-side wants to live where the workspace service can |
| 646 | + hand it to the model (a `clients`-table field in the canonical layer, or |
| 647 | + a workspace-service-owned doc). Decide in the plan; lean server-side so |
| 648 | + chat and button share one source of truth. |
| 649 | + |
| 650 | +### v1.2 open questions |
| 651 | + |
| 652 | +- [ ] Crawl substrate: drive `search.fire`/packs, or the Firecrawl/Tavily |
| 653 | + connectors directly with agent-composed queries? (The packs already |
| 654 | + encode per-target shapes; lean packs-first.) |
| 655 | +- [ ] Relevance brief storage (above) — localStorage floor vs |
| 656 | + workspace-service-owned per-client doc. Lean server-side. |
| 657 | +- [ ] Does the crawl surface reuse search-and-add's ResultRow/candidate UI |
| 658 | + (likely — same accept-per-row gate) or stage into the chat rail? |
| 659 | +- [ ] Chat rail placement: the didi-chat plan owns whether the rail is the |
| 660 | + existing `apps/chat` remote or a workbench-embedded rail — this spec only |
| 661 | + requires the capability be callable from both rail and button. |
| 662 | + |
572 | 663 | ## Handoff notes (what makes >70% first-go likely) |
573 | 664 |
|
574 | 665 | - Every new file has a **named template in-repo**: remote scaffold ← `apps/person-db-resolver`; client lib ← `apps/record-db-resolver/src/lib/resolver-client.ts`; service fns ← `resolver.ts` / `person-resolver.ts` neighbors; connector ← `connectors/tavily.ts`; registration ← `TAVILY_REG`; NATS handler blocks ← any block in `handlers.ts`. |
|
0 commit comments