Skip to content

Commit 686cdf9

Browse files
authored
Merge pull request #43 from lossless-group/feature/search-results-queue
Searches become async jobs — the search-results queue rail (spec Phases 1–3)
2 parents 3e07b20 + cd789d8 commit 686cdf9

37 files changed

Lines changed: 2022 additions & 501 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@ pnpm-debug.log*
5050
# Local agent + ad-hoc data backups
5151
.claude/
5252
.backups/
53+
54+
# Playwright MCP browser-drive artifacts (session snapshots/logs)
55+
.playwright-mcp/

apps/org-workbench/src/OrgCard.svelte

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import PeopleReveal from './PeopleReveal.svelte';
1010
import { addOrgLink, addOrgStream, updateOrgStream, addOrgCorpus } from './lib/org-client';
1111
import { requestSearch } from './lib/search-request';
12+
import { submitCrawl } from './lib/search-queue';
1213
import type { OrgDetail, SearchRequestDetail, StreamEntry } from './lib/types';
1314
1415
let {
@@ -59,16 +60,16 @@
5960
});
6061
}
6162
62-
// 🤖 — didi's crawl for a whole list (v1.2): same envelope, crawl flag on;
63-
// search-and-add's crawl mode fires organization.crawl instead of a term.
63+
// 🤖 — didi's crawl for a whole list, enqueued as an async job: the search
64+
// lands as a card in the search-results rail (which the shell flips
65+
// visible), no column hijack, no babysitting. Replaces the v1.2
66+
// search-and-add crawl mode per the Search-Results-Queue-Remote spec.
6467
function makeCrawl(target: 'links' | 'streams') {
65-
return () =>
66-
requestSearch({
67-
entity: { type: 'organization', org_slug: org.slug, display_name: displayName },
68-
target,
69-
seed_term: '',
70-
crawl: true,
71-
});
68+
return () => {
69+
void submitCrawl({ org_slug: org.slug, display_name: displayName, target, client }).catch(
70+
(err) => console.warn('[org-workbench] search.submit failed', err),
71+
);
72+
};
7273
}
7374
</script>
7475

apps/org-workbench/src/PeopleReveal.svelte

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import { onMount } from 'svelte';
1010
import PersonCard from './PersonCard.svelte';
1111
import AddPersonInline from './AddPersonInline.svelte';
12-
import StagedPeople from './StagedPeople.svelte';
13-
import { fetchOrgAffiliations, crawlTeam, type CrawledPerson } from './lib/org-client';
12+
import { fetchOrgAffiliations } from './lib/org-client';
13+
import { submitCrawl } from './lib/search-queue';
1414
import type { AffiliatedPerson } from './lib/types';
1515
1616
let {
@@ -30,28 +30,21 @@
3030
let error = $state<string | null>(null);
3131
let expanded = $state<string | null>(null); // person_uuid
3232
33-
// didi's team crawl (v1.2) — staged candidates, never auto-written.
34-
let crawling = $state(false);
33+
// didi's team crawl — enqueued as an async job; candidates land as a card
34+
// in the search-results rail (staging + accept gates live there now, per
35+
// the Search-Results-Queue-Remote spec). The transient note is the only
36+
// local feedback the door needs.
37+
let queued = $state(false);
3538
let crawlError = $state<string | null>(null);
36-
let crawlGen = $state(0); // bumps per crawl so StagedPeople remounts fresh
37-
let staged = $state<{
38-
people: CrawledPerson[];
39-
filtered_note: string;
40-
source_urls: string[];
41-
} | null>(null);
4239
4340
async function crawl() {
44-
crawling = true;
4541
crawlError = null;
4642
try {
47-
const r = await crawlTeam(org_slug, client);
48-
staged = r;
49-
crawlGen += 1;
50-
if (!open) toggle();
43+
await submitCrawl({ org_slug, display_name: orgName, target: 'team', client });
44+
queued = true;
45+
setTimeout(() => (queued = false), 5_000);
5146
} catch (err) {
5247
crawlError = err instanceof Error ? err.message : String(err);
53-
} finally {
54-
crawling = false;
5548
}
5649
}
5750
@@ -74,10 +67,15 @@
7467
}
7568
7669
function onEntityUpdated(e: Event) {
77-
const detail = (e as CustomEvent).detail as { person_uuid?: string } | undefined;
78-
if (detail?.person_uuid && loaded && people.some((p) => p.person_uuid === detail.person_uuid)) {
70+
const detail = (e as CustomEvent).detail as { person_uuid?: string; org_slug?: string } | undefined;
71+
if (!loaded) return;
72+
if (detail?.person_uuid && people.some((p) => p.person_uuid === detail.person_uuid)) {
7973
void load();
74+
return;
8075
}
76+
// Org-shaped events cover the search rail's team accepts (TeamAccept
77+
// writes person + affiliation, then broadcasts with the org_slug).
78+
if (detail?.org_slug && detail.org_slug === org_slug) void load();
8179
}
8280
8381
// A new org card means fresh people — reset and lazy-load on next reveal.
@@ -86,7 +84,6 @@
8684
people = [];
8785
loaded = false;
8886
expanded = null;
89-
staged = null;
9087
crawlError = null;
9188
if (open) void load();
9289
});
@@ -108,15 +105,14 @@
108105
<button
109106
type="button"
110107
class="ow-plus"
111-
title="didi: crawl the web for relevant team members (selection per the relevance brief)"
112-
disabled={crawling}
108+
title="didi: crawl the web for relevant team members (selection per the relevance brief) — lands in the search queue"
113109
onclick={crawl}
114110
>
115-
{crawling ? '' : '🤖'}
111+
🤖
116112
</button>
117113
</span>
118114
</header>
119-
{#if crawling}<p class="ow-empty">didi is crawling for team members — this takes a minute…</p>{/if}
115+
{#if queued}<p class="ow-empty">team search queued — it lands in the 🔎 search rail when done; keep working</p>{/if}
120116
{#if crawlError}<div class="ow-error">{crawlError}</div>{/if}
121117

122118
{#if open}
@@ -151,20 +147,6 @@
151147
{/each}
152148
</ul>
153149
{/if}
154-
{#if staged}
155-
{#key crawlGen}
156-
<StagedPeople
157-
{org_slug}
158-
{orgName}
159-
{client}
160-
people={staged.people}
161-
filtered_note={staged.filtered_note}
162-
source_urls={staged.source_urls}
163-
onchanged={load}
164-
onclear={() => (staged = null)}
165-
/>
166-
{/key}
167-
{/if}
168150
<AddPersonInline {org_slug} {orgName} {client} onadded={load} />
169151
{/if}
170152
{/if}

apps/org-workbench/src/StagedPeople.svelte

Lines changed: 0 additions & 200 deletions
This file was deleted.

0 commit comments

Comments
 (0)