mirror of
https://github.com/prdlk/jobyssey.git
synced 2026-11-02 13:12:49 +00:00
docs(claude): clarify Fastmail requirement and add Twenty CRM sync steps to rank and scraper docs
This commit is contained in:
1 parent
1884510414
commit
12f7f4d9dc
3 files changed
+26
-1
No files matched your search
@@ -25,7 +25,7 @@ Follow these steps **in order**.
|
|||||||
|
|
||||||
Silently optional, same bar as `/sync-twenty`: a missing prerequisite ends in one clear message and a clean exit.
|
Silently optional, same bar as `/sync-twenty`: a missing prerequisite ends in one clear message and a clean exit.
|
||||||
|
|
||||||
1. **Fastmail MCP** must be available (tools like `search_email`, `read_thread`). If not, say so and stop.
|
1. **Fastmail** must be reachable one way or the other: the **Fastmail MCP** tools (`search_email`, `read_thread`, `search_events`) in an interactive session, **or** `FASTMAIL_API_TOKEN` in the environment for the headless JMAP client (`python3 tools/fastmail_client.py search|thread|events|draft|reply` - same search surface, plus calendar and reply-drafting; drafts only, it never sends). Neither → say so and stop.
|
||||||
2. **Twenty** must be reachable one way or the other: `TWENTY_API_KEY` in the environment (script applies via REST) **or** the Twenty MCP session (you apply the plan). Neither → one line and stop.
|
2. **Twenty** must be reachable one way or the other: `TWENTY_API_KEY` in the environment (script applies via REST) **or** the Twenty MCP session (you apply the plan). Neither → one line and stop.
|
||||||
3. Never initiate an OAuth flow from this command.
|
3. Never initiate an OAuth flow from this command.
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,21 @@ Do not modify `job_search_tracker.csv` - that file records applications, and `/r
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Step 4.5: Sync the Delta to Twenty CRM
|
||||||
|
|
||||||
|
`/rank` is the moment a posting becomes an opportunity, so the run pushes its own delta to Twenty instead of waiting for a manual `/sync-twenty`. **Silently optional**: if the Twenty MCP tools (`execute_tool` meta-tool / `mcp__twenty_*` devices) are not available in this session, or the one cheap preflight call fails, say so in one line inside the Step 5 report and skip this step - the ranking result above is complete without it, and the next `/sync-twenty` run will catch the CRM up.
|
||||||
|
|
||||||
|
Follow the `/sync-twenty` contract exactly (it is the single source of truth for field maps, enum tables, batch caps, and idempotency rules) - this step is that command scoped to **this run's delta**:
|
||||||
|
|
||||||
|
1. **Newly ranked jobs** (this run's Step 4 writes): ensure each employer's Company record exists (`/sync-twenty` Steps 4-5: dedup on normalized name, enrich via `tools/twenty_enrich.py` local layer, never overwrite existing records), then create the Opportunity (`/sync-twenty` Step 6: dedup on posting URL, `stage: RANKED`, score/verdict/url/location/`companyId`, batches ≤ 20) and its Fit Analysis note (`/sync-twenty` Step 8).
|
||||||
|
2. **Newly expired entries** (this run's rule 6 sweep and dead-posting marks): if the posting URL already has an Opportunity, set its `stage` to `EXPIRED` via `upsert_many_opportunities` with the explicit `id` (assert zero creates). Never delete records.
|
||||||
|
3. **Salary + name cleanup** (`/sync-twenty` Step 7) run only over the records this step touched.
|
||||||
|
4. Add one line to the Step 5 report: `Twenty CRM: <N> opportunities created, <E> expired, <C> companies created (or: skipped - not connected).`
|
||||||
|
|
||||||
|
Everything created here is what a subsequent full `/sync-twenty` would create - running both never duplicates (both dedup on the same posting-URL / normalized-name keys).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Step 5: Present the Shortlist
|
## Step 5: Present the Shortlist
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -196,6 +196,16 @@ Scraper-based portal CLIs rot silently: when a portal changes its markup, the pa
|
|||||||
|
|
||||||
**Probe-only mode (`/scrape health`).** Skip Steps 1-4 and this step's free pass (there is no fresh run to scan); instead probe every installed portal directly - enabled ones by default, a disabled one only when named explicitly (e.g. `/scrape health jobnet`). Each portal gets the sentinel probe above, the degraded criteria applied to whatever it returns, and - since the user explicitly asked for diagnosis - one `detail` fetch on the first result of each healthy portal (description must be readable decoded text; a failure downgrades to degraded). Report all statuses in this mode, including healthy. Volume stays bounded: one search, at most one retry, at most one detail per portal.
|
**Probe-only mode (`/scrape health`).** Skip Steps 1-4 and this step's free pass (there is no fresh run to scan); instead probe every installed portal directly - enabled ones by default, a disabled one only when named explicitly (e.g. `/scrape health jobnet`). Each portal gets the sentinel probe above, the degraded criteria applied to whatever it returns, and - since the user explicitly asked for diagnosis - one `detail` fetch on the first result of each healthy portal (description must be readable decoded text; a failure downgrades to degraded). Report all statuses in this mode, including healthy. Volume stays bounded: one search, at most one retry, at most one detail per portal.
|
||||||
|
|
||||||
|
### Step 4.9: Twenty CRM Catch-Up (silently optional)
|
||||||
|
|
||||||
|
The CRM pipeline starts at `ranked` (a scraped-but-unranked job is not yet an opportunity - `/rank` Step 4.5 is what promotes it), but a scrape run is still a natural moment to keep Twenty current. If the Twenty MCP tools (`execute_tool` meta-tool / `mcp__twenty_*` devices) are available in this session - never probe via shell, and skip this step with one report line when they are not:
|
||||||
|
|
||||||
|
1. **Catch-up delta:** find `seen_jobs.json` entries with status `ranked` or `expired` whose posting URL has no Opportunity in Twenty (page `find_many_opportunities` for the URL map). Sync them per the `/sync-twenty` contract (companies → opportunities → fit notes; batches ≤ 20; dedup on posting URL / normalized company name). This heals any gap left by a `/rank` run that executed while Twenty was unreachable.
|
||||||
|
2. **Expiry refresh:** entries this run re-encountered whose stored status is `expired` but whose CRM `stage` is not `EXPIRED` get a stage update via `upsert_many_opportunities` with the explicit `id` (assert zero creates).
|
||||||
|
3. Add one line to the Step 5 summary: `Twenty CRM: <N> caught up, <E> expired (or: skipped - not connected).`
|
||||||
|
|
||||||
|
This step never blocks the scrape: any Twenty failure is one report line, and the next `/rank` or `/sync-twenty` run picks up the same delta (all three dedup on the same keys, so nothing ever duplicates).
|
||||||
|
|
||||||
### Step 5: Present Results
|
### Step 5: Present Results
|
||||||
|
|
||||||
Present new jobs in a table sorted by fit (high first). When Step 1b skipped
|
Present new jobs in a table sorted by fit (high first). When Step 1b skipped
|
||||||
|
|||||||
Reference in new issue
Block a user