# Workflow Reference

## Contents

- Stage 1 endpoint sequence
- Stage 1 coverage gate
- Role-evidence expansion
- Stage 2 interaction sequence
- Adaptive pagination
- Failure handling

## Stage 1 Endpoint Sequence

Resolve the official handle with `graphql_user_by_screen_name`. Preserve its numeric user ID, BusinessLabel metadata, and `business_account.affiliates_count`.

Fetch `graphql_user_business_profile_team_timeline` with:

```json
{
  "userId": "<official numeric id>",
  "cursor": "",
  "count": 100,
  "teamName": "NotAssigned",
  "includePromotedContent": false,
  "withClientEventToken": false,
  "withVoice": true
}
```

Follow each Bottom cursor. Stop on an empty page, no Bottom cursor, or a repeated cursor. Deduplicate users by numeric ID.

If the endpoint fails or returns fewer affiliates than the official profile reports, paginate `graphql_following` and retain only users whose BusinessLabel URL or description identifies the official account. Treat this as a supplement, not weaker heuristic membership evidence.

## Stage 1 Coverage Gate

Set `coverage.complete` only when:

1. Discovered affiliate count exactly matches the official profile count.
2. Cursor traversal terminates with an empty page or no cursor.

A mismatch or non-terminal repeated cursor stays incomplete. Stage 2 rejects incomplete evidence by default.

The default affiliate cap is 20 pages. If `primary_stop_reason` or `fallback_stop_reason` is `max_pages`, rerun into a fresh directory with a larger `--affiliate-max-pages N`; do not edit `coverage.complete` manually.

## Role-Evidence Expansion

Evaluate the bio first. When it does not explicitly tie a role to the target organization:

1. Fetch up to two `graphql_user_tweets_and_replies` pages.
2. Keep only tweets authored by that member; nested conversation tweets from others are not member evidence.
3. Search combinations of `from:<member>`, the official handle, the organization name, and the member's name.
4. Store query, tweet ID, URL, text, author, and timestamp.

The service proposes candidates. A reviewer confirms the current role.

## Stage 2 Interaction Sequence

Validate `team-review.json` before any calls. Build the exclusion set from the official account plus every confirmed affiliate, using both user ID and lowercased handle.

For each source member, fetch `graphql_user_tweets_and_replies`. Normalize and deduplicate authored tweets, then extract:

- reply target from `in_reply_to_*` or reply context;
- quote target from quoted author context;
- mentions from normalized user entities;
- retweet target from retweeted author context.

Count a target at most once per tweet and interaction type. Retain individual counts, total, distinct source-member count, tweet IDs, dates, and evidence snippets.

Resolve a bounded, ranked superset of interaction edges with `UserByRestId` or `UserByScreenName`. If profile evidence does not establish both target relationship and role, fetch candidate timelines and SearchTimeline evidence before review.

The default profile-resolution cap is `max(120, 4*candidate-limit)` raw edges. The service then merges ID-only/handle-only aliases before applying the score threshold and candidate limit. The default candidate selection is score `>=2`, first 30 merged candidates. Inspect `interaction_collection_truncated`, `interaction_truncated_members`, `raw_interaction_edges`, all three profile-resolution attempted/succeeded/failed counts, `candidate_resolution_truncated`, `eligible_candidates`, `investigated_candidates`, and `candidate_pool_truncated`. Increase the relevant interaction, resolution, or candidate cap; use `--min-candidate-score 1` when an exhaustive request must include single-retweet candidates. The review gate requires `candidate_pool_acknowledged: true`.

## Adaptive Pagination

Use sparse-evidence checkpoints at pages 2, 5, and 10, with `--interaction-max-pages` as the actual hard cap. At a checkpoint below the cap, continue when either total interactions or unique external candidates is below its configured target. A cap above 10 allows sparse runs to continue beyond page 10. Always stop on empty response, missing cursor, or repeated cursor. Never manufacture extra pages when the API is exhausted.

## Failure Handling

- Retry network failures, HTTP 429, and HTTP 5xx within the client's finite retry budget.
- Do not retry ordinary HTTP 4xx errors.
- Record optional role/candidate search failures in evidence instead of discarding the rest of the run.
- Fail the stage when the official profile or required direct-team data cannot be obtained.
- Never include API keys, auth tokens, or proxy credentials in errors or output.
