Skip to content

feat(enrichment): stay active until enrichment done, self-report results#154

Merged
ArtyETH06 merged 27 commits into
mainfrom
ArtyETH06/wait-for-tool-result-in-enrhichment
Jul 9, 2026
Merged

feat(enrichment): stay active until enrichment done, self-report results#154
ArtyETH06 merged 27 commits into
mainfrom
ArtyETH06/wait-for-tool-result-in-enrhichment

Conversation

@ArtyETH06

@ArtyETH06 ArtyETH06 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What & why

Launching an enrichment (leadbay_enrich_titles) kicks off an async backend job and returns immediately. The agent used to end its turn on that ack, so the user had to reprompt ("is it done yet?") to see results.

Now the agent stays active in the same turn: it polls leadbay_bulk_enrich_status until the job is done, then reports the resolved emails/phones + counts in-reply, without a reprompt.

"Done" = all_done, OR progress plateaus — total counts every matching contact and some (unresolvable titles, no findable email) never flip, so all_done can stay false forever. When overall_progress.done stops climbing across a few polls, the agent reports what resolved (naming the ones that didn't) instead of spinning forever or deferring to a scheduled re-check.

Changes

  • snippets/gates/notifications-inbox.md — reverse the flat "Don't poll" rule, split by when the job launched: previous-turn jobs still ride the _meta.notifications push; a job launched THIS turn gets polled to completion.
  • enrich-titles.md.tmpl — new "AFTER LAUNCH — STAY ACTIVE UNTIL DONE" section with the plateau safety-valve. bulk-enrich-status.md.tmpl — poll-repeatedly contract + completion-report section.
  • bulk-enrich-status.ts — the notification fast path now returns per-lead contacts on any include_contacts read (not only when terminal), and surfaces credits_remaining on any report read. Without this, a plateau report (in_progress:true forever) returned bare {lead_id} with no contact data — the report the guidance asks for was unfulfillable.
  • enrich-titles.ts / enrich-contacts.ts / launch-bulk-enrichment.ts — runtime message/next_action/hint strings updated to instruct active polling (string-only; no logic change).
  • WORKFLOWS.md — new Workflow 43 (single-turn, automatic stay-active; distinct from WF34's multi-turn "wait for enrichment" prompt).
  • New unit tests bulk-enrich-poll-until-done.test.tsall_done flips false→true across sequential polls; a plateau read (in_progress:true + include_contacts) returns contacts + balance; an interim poll stays cheap (one /notifications call, no fan-out).
  • Eval harness live-mcp-server.ts — wire a BulkTracker + NotificationsInbox so leadbay_bulk_enrich_status can actually be polled in evals (previously errored "No BulkTracker configured", which blocked WF34's turn-3 poll too).

Eval (live, latest run — Workflow 43, on the current head 155d52b4)

Prompt: "Pull my current leads, then enrich the CEO, Owner and Manager emails on the top 5 — go ahead and spend, email channel — and give me the finished results in this same reply, don't make me ask again."

MM 5 / IA 5 / NF 5 / TSF 5 · invariants PASS (required + order + forbidden).
pull_leads → enrich_titles (launched, bulk_id, enrichable_contacts:3) → bulk_enrich_status ×5 (spaced ~20–30s, include_contacts on the report reads) → account_status. The agent launched the paid enrichment, stayed active and polled to settlement, then reported per-lead results in the same reply. This run exercised the plateau path directly: overall_progress.done held at 0/1 with no partial_failures across the spaced polls, so the agent correctly treated the requested contacts reaching enrichment.done:true as terminal (not spinning for a never-true all_done, not misreading the flat count as a transient failure), delivered the one landed email (michael@p1padel.com) + named the four that didn't resolve, and refreshed quota via account_status. No fabricated emails — the single reported email is the only enriched email in any tool result.

Not covered: runs under the eval's fallback system prompt (not the shipped host routing). The clean all_done:true-terminal branch (vs the plateau branch this run hit) is covered deterministically by the unit tests.

Gates

pnpm prompts:build · pnpm -r build · pnpm -r test (components 47, core 556, promptforge 16, mcp 525) · pnpm -r typecheck — all green. Budget/workflows/routing/version audits pass. GitHub build-and-test CI green.

Closes https://github.com/leadbay/product/issues/3866

@ArtyETH06 ArtyETH06 self-assigned this Jul 8, 2026
@ArtyETH06 ArtyETH06 marked this pull request as ready for review July 8, 2026 15:06
@ArtyETH06 ArtyETH06 marked this pull request as draft July 8, 2026 15:08
github-actions Bot and others added 4 commits July 8, 2026 08:12
Launching an enrichment (leadbay_enrich_titles) kicks off an async backend
job and returns immediately. The agent used to end its turn on that ack, so
the user had to reprompt ("is it done yet?") to see results.

Now the agent stays active in the same turn: it polls leadbay_bulk_enrich_status
until the job is done — all_done, OR progress plateaus (some contacts are
unresolvable and never flip, so all_done can stay false forever) — then reports
the resolved emails/phones + counts in-reply, without a reprompt and without
deferring to a scheduled re-check.

- Reverse the "Don't poll" rule in snippets/gates/notifications-inbox.md: split
  by WHEN the job launched — previous-turn jobs still ride the _meta.notifications
  push; a job you launched THIS turn gets polled to completion.
- enrich-titles.md.tmpl: add "AFTER LAUNCH — STAY ACTIVE UNTIL DONE" with the
  plateau safety-valve; bulk-enrich-status.md.tmpl: poll-repeatedly contract +
  completion-report section.
- enrich-titles.ts / enrich-contacts.ts / launch-bulk-enrichment.ts: update the
  runtime message/next_action/hint strings to instruct active polling (no logic
  change).
- WORKFLOWS.md: new Workflow 43 (single-turn, automatic stay-active — distinct
  from WF34's multi-turn "wait for enrichment" prompt).
- New unit test proves all_done flips false->true across sequential polls.
- Eval harness: wire a BulkTracker + NotificationsInbox into live-mcp-server so
  leadbay_bulk_enrich_status can actually be polled in evals.

Co-Authored-By: Claude <noreply@anthropic.com>
…ude_contacts)

Codex P1: the stay-active guidance tells the agent to stop on a plateau and
report the RESOLVED contacts, but bulk_enrich_status's notification fast path
gated the per-lead fan-out on `!inProgress && includeContacts` — so at a
plateau (in_progress:true forever, some contacts unresolvable) an
include_contacts read returned bare {lead_id} with no contact data, making the
report unfulfillable.

- Fan out on `includeContacts` alone, regardless of in_progress. The agent only
  sets include_contacts on the read it reports from, so interim polls
  (default false) stay cheap.
- Surface credits_remaining on any report read (terminal OR plateau), not only
  terminal — same opt-in cost boundary.
- New tests: plateau report returns contacts + balance while in_progress;
  interim poll stays cheap (one /notifications call, no fan-out, no /me).

Co-Authored-By: Claude <noreply@anthropic.com>
Codex P2: the shared notifications-inbox snippet told the agent to poll every
status tool "until all_done or a done-count plateau", but only
leadbay_bulk_enrich_status returns all_done. Qualify signals completion via an
empty still_running[] (in_progress:false); import via status:"complete".
The blanket all_done rule risked the agent over-polling or ignoring the real
terminal response for qualify/import.

Spell out each status tool's own terminal signal in the current-turn polling
rule. Enrichment keeps its all_done/plateau semantics; qualify and import get
their correct fields. Enrichment-specific templates (enrich-titles,
bulk-enrich-status) were already correct and are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Minor bump for the stay-active enrichment feature (product#3866).
package.json + server.json (top-level, packages[].version, and the
@leadbay/mcp@<major.minor> npx pins all track 0.24).

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc1771102a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl Outdated
Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
@ArtyETH06 ArtyETH06 closed this Jul 8, 2026
@ArtyETH06 ArtyETH06 reopened this Jul 8, 2026
@ArtyETH06 ArtyETH06 force-pushed the ArtyETH06/wait-for-tool-result-in-enrhichment branch from fc17711 to 83d8f21 Compare July 8, 2026 15:25
…nch, fallback counts, test mock

- enrich-titles.ts: branch the launched-mode message/next_action on bulkRecord
  (real bulk_id) BEFORE notification_id. A notification_id can return with no
  tracker (legacy/OpenClaw raw launch), leaving bulk_id undefined — the agent
  must use the per-lead fallback, not poll a nonexistent bulk_id. [Codex #789]
- enrich-titles.md.tmpl + notifications-inbox.md: a plateau is only real after
  ~90s–2min of SPACED polls, not the first few back-to-back reads (done sits
  flat while the backend spins up). [Codex #784]
- bulk-enrich-status.md.tmpl: don't promise bulk_progress unconditionally — the
  legacy fan-out fallback returns overall_progress only; derive counts from it
  there. [Codex #793]
- bulk-enrich-poll-until-done.test.ts: the terminal include_contacts test now
  mocks the per-lead contact GETs and asserts contacts come back, so a swallowed
  fetch error can't mask an empty result. [Codex #798]
- (Codex #806 — contacts on plateau — already fixed in 4fef5e8.)

Co-Authored-By: Claude <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 marked this pull request as ready for review July 8, 2026 15:39

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59dcf16b43

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
Comment thread packages/promptforge/snippets/gates/notifications-inbox.md Outdated
Comment thread packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl Outdated
Comment thread WORKFLOWS.md
…plates + gate quota call

Follow-ups after the prior round found the same fixes needed in sibling surfaces:

- enrich-titles.md.tmpl: AFTER LAUNCH no longer promises bulk_progress
  unconditionally — mirrors the status-tool wording (fast path has it, legacy
  fan-out returns overall_progress only). [Codex]
- bulk-enrich-status.md.tmpl: plateau rule now requires spaced polls over
  ~90s–2min elapsed, not "a few polls" — mirrors the launch guidance. [Codex]
- notifications-inbox.md: the previous-turn "don't poll" rule now applies only
  to ambient/background completion; when the user explicitly asks for status or
  "wait for it to finish" (e.g. WF34 turn 3), the agent DOES poll. [Codex]
- WORKFLOWS.md WF43: add leadbay_account_status to required_calls + required_order
  so the deterministic precheck enforces the quota refresh (not just the judge). [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 marked this pull request as draft July 8, 2026 15:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 449f98c314

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread WORKFLOWS.md
Comment thread packages/mcp/test/eval/helpers/live-mcp-server.ts Outdated
Comment thread packages/promptforge/snippets/gates/notifications-inbox.md Outdated
…p scope, eval store isolation

- enrich-titles.ts: the no-BulkTracker (legacy/OpenClaw) fallback next_action now
  carries the same plateau/timeout escape as the bulk-id branch — stop once the
  done set stops growing over ~90s–2min, don't poll leadbay_get_contacts forever
  on unresolvable contacts. [Codex]
- notifications-inbox.md: scope the stay-active poll loop — imports are the
  exception (a large wait_for_completion:false import returns a handle and
  resolves over minutes; the tool does one refresh pass), so don't block looping
  on import_status unless the user asked to wait or it's a quick import. [Codex]
- live-mcp-server.ts (eval helper): use InMemoryBulkStore instead of the
  file-backed createDefaultBulkStore, so repeated eval sessions don't share
  ~/.leadbay/bulks.json and hit the 5-min idempotency window (which would reuse a
  prior record and skip the backend launch the eval is meant to exercise). [Codex]

(required_order — kept: it IS enforced, by the /eval skill Phase 4, just not by
the workflows.test.ts unit audit; replying to clarify.)

Co-Authored-By: Claude <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 marked this pull request as ready for review July 8, 2026 16:23
@ArtyETH06 ArtyETH06 requested a review from milstan July 8, 2026 16:23

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d53811c575

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/tools/enrich-contacts.ts Outdated
Comment thread WORKFLOWS.md
Comment thread packages/promptforge/snippets/gates/notifications-inbox.md Outdated
Comment thread packages/core/src/tools/launch-bulk-enrichment.ts Outdated
Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
…l-aware wording, tighten WF43

- enrich-titles.ts: already_launched (idempotent reuse) branch next_action now
  carries the spaced-plateau/elapsed escape — a reused bulk with unresolvable
  contacts can stay all_done:false forever. [Codex]
- enrich-contacts.ts + launch-bulk-enrichment.ts: single-contact and granular
  bulk hints now bound the wait (~90s–2min spaced re-checks), then report the
  unresolved contact/remainder instead of polling get_contacts forever. [Codex]
- enrich-titles.md.tmpl: plateau "didn't resolve" wording is now channel-aware
  (no phone / no email / no contact details / quota-hit), not hard-coded
  "no email found" — correct for phone-only and email+phone runs. [Codex]
- notifications-inbox.md: qualify terminal signal = still_running empty on its
  own; require in_progress:false only when present (it's null on legacy/fallback
  reads, else the agent polls a completed job forever). [Codex]
- WORKFLOWS.md WF43: require leadbay_pull_leads (first) + a success criterion to
  scope enrichment to the top 5 (picked leadIds / candidateCount:5), so a run
  can't use the default candidate set and overspend quota. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1290adca4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
Comment thread packages/mcp/test/eval/helpers/live-mcp-server.ts Outdated
…sion eval store

- enrich-titles.md.tmpl + bulk-enrich-status.md.tmpl: the channel-aware plateau
  wording now checks phone_number (the field leadbay_get_contacts actually
  returns), not phone — a successful phone reveal was being mislabeled "no phone
  number found". [Codex]
- live-mcp-server.ts (eval helper): swap the in-memory store for a PER-SESSION
  file store (LEADBAY_BULK_STORE_PATH, else a per-process path under ~/.leadbay).
  In-memory was lost between turns — the live runner spawns a fresh process per
  turn, so WF34 turn 3's bulk_enrich_status poll would BULK_NOT_FOUND the record
  turn 2 launched. A per-session file survives across the session's turns while
  staying isolated from other runs (fixes the round-3 idempotency-reuse concern
  without breaking multi-turn). [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e04887a9b3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread WORKFLOWS.md Outdated
…us poll (WF43)

The "polled REPEATEDLY (more than once)" success criterion was unconditional, so
a correct same-turn run whose FIRST leadbay_bulk_enrich_status read already
returns all_done (small / already-enriched / fast backend) would be judged as
failing just for not making a redundant second poll. Make repeated polling
conditional: one poll is correct when the first read is already all_done;
otherwise keep polling while still in-progress. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0af173ad74

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/mcp/test/eval/helpers/live-mcp-server.ts
Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
…re path + filter report to titles

- live-session-runner.ts: the round-5 per-session store fix was only half done —
  the helper honored LEADBAY_BULK_STORE_PATH but the runner never set it, so it
  fell back to the per-process path and multi-turn still broke. Now writeMcpConfig
  sets LEADBAY_BULK_STORE_PATH to ~/.leadbay/bulks.eval.<session_id>.json, stable
  across the session's per-turn server processes so WF34 turn 3 finds turn 2's
  bulk. [Codex]
- enrich-titles.md.tmpl + bulk-enrich-status.md.tmpl: include_contacts returns
  each lead's FULL contact list (get_contacts fan-out), so the report guidance now
  says to FILTER to the enriched `titles` (match job_title) — don't attribute a
  pre-existing CFO/Sales email to a CEO/Owner/Manager run. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56001a3187

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl Outdated
Comment thread packages/promptforge/snippets/gates/notifications-inbox.md Outdated
github-actions Bot and others added 2 commits July 8, 2026 13:41
…ing lead_ids, bg-request, channel-scoped fallback

- enrich-titles.ts already_launched: a reused record can be stuck status:pending
  (original launch hit launched_tracker_pending). Route pending reuse to the
  per-lead fallback (with lead_ids), not bulk_enrich_status/BULK_PENDING. [Codex]
- enrich-titles.ts launched_tracker_pending: include lead_ids in the response so
  the agent has identifiers to poll per-lead (leadIds may have come from the
  wishlist default). [Codex]
- enrich-titles.md.tmpl: honor an explicit "don't wait / background" request —
  hand back the bulk_id + let _meta.notifications deliver, instead of forcing the
  poll loop against user intent. Stay-active stays the default. [Codex]
- bulk-enrich-status.ts: legacy fallback "done" is now channel-aware — a
  title-matching contact only counts as done when the REQUESTED channel resolved
  (record.email → email present; record.phone → phone_number present). Stops a
  phone-only run from reading all_done:true off a pre-existing email enrichment.
  New phone-only test + /users/me mock added to the title-scope test. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>
…ol-result-in-enrhichment

# Conflicts:
#	packages/mcp/server.json
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Synced with main; @leadbay/mcp is 0.24.0 (main shipped 0.23.14).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 251438438d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
…d_ids in no-tracker launch

- enrich-titles.ts already_launched: only treat a reused pending record as STUCK
  when it's aged (>=60s). A fresh concurrent pending is the normal serialization
  point between the first call's findOrCreatePending and markLaunched — it flips
  to launched momentarily, so the second caller should poll bulk_enrich_status as
  usual, not be told the job is unhealable. Distinguish by seconds_since_original. [Codex]
- enrich-titles.ts mode:"launched": include lead_ids in the response so the
  no-tracker branch (no bulk_id, caller may have used the wishlist default) gives
  the agent concrete identifiers to follow the job per-lead. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 423d99113c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/promptforge/snippets/gates/notifications-inbox.md Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
…xception in gate, no-notif message

- enrich-titles.ts: an aged (>=60s) pending reuse is ambiguous — pre-launch crash
  (no backend job) vs post-launch markLaunched failure (job ran). The record can't
  tell them apart, so reusing + "don't relaunch" risks polling for nonexistent
  work. Since re-launch is server-idempotent, retire the aged pending (markFailed)
  and fall through to a fresh launch. Fresh concurrent pending (<60s) still reuses.
  New aged-pending relaunch test (injectable clock). [Codex]
- enrich-titles.ts: the launched message no longer promises _meta.notifications
  completion when notification_id is null — that path has nothing to correlate, so
  it tells the agent/user to poll leadbay_bulk_enrich_status again later instead. [Codex]
- notifications-inbox.md: the shared gate now mirrors the background-request
  exception (and the no-notification-id caveat), so prompt surfaces using this
  snippet don't override an explicit "don't wait" with a forced poll loop. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db3ad6f78d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/promptforge/tool-descriptions/composite/enrich-titles.md.tmpl Outdated
Comment thread packages/mcp/package.json
…aveats, plateau quota, 0.24.0 changelog

- enrich-titles.ts: the launched next_action now honors an explicit no-wait
  request (hand back the handle instead of forcing the poll loop) — the runtime
  string is the newest instruction the agent sees, so the prompt-only exception
  wasn't enough. [Codex]
- enrich-titles.md.tmpl: the background exception now conditions the
  _meta.notifications promise on a non-null notification_id (nullable-backend path
  has nothing to correlate → tell the user to ask again later). [Codex]
- server-instructions/quota-topup.md: refresh quota when the job is done —
  all_done OR a terminal plateau — not only all_done, so plateau completions still
  report refreshed quota. [Codex]
- CHANGELOG.md: add the 0.24.0 section so the release workflow publishes real
  feature notes instead of the generic fallback. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d0462b061

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/tools/enrich-contacts.ts Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
…t hint + plateau in launch messages

- enrich-contacts.ts: the single-contact hint now keys "done" off the REQUESTED
  channel's field (email → email present; phone → phone_number present), built
  dynamically from the requested channels — not contact.enrichment.done alone,
  which is already true for a contact previously enriched on the other channel
  (a phone reveal could be reported before phone_number lands). [Codex]
- enrich-titles.ts: the mode:"launched" message strings (both notification and
  no-notification branches) now carry the plateau escape too — poll until all_done
  OR until overall_progress.done plateaus — matching next_action. The message is
  the immediate instruction the agent reads, so without it agents could poll
  all_done forever on unresolvable contacts. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0556afeaf0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/tools/launch-bulk-enrichment.ts Outdated
…el-aware "done" + no-wait everywhere

The round-15 findings were the last string variants of two rules already fixed
in code + other strings: (1) a contact is "done" only when the REQUESTED channel
landed (email/phone_number), not contact.enrichment.done alone; (2) honor an
explicit no-wait request.

Round-15 fixes:
- bulk-enrich-status.md.tmpl COMPLETION REPORT: derive counts from overall_progress
  + requested fields, not the enrichment.done flag.
- enrich-titles.ts no-tracker message + next_action: channel-aware done.
- launch-bulk-enrichment.ts hint: channel-aware done (dynamic from requested channels).
- enrich-titles.ts already_launched next_action: honor no-wait.

Consolidation sweep (so future rounds stop finding one variant at a time):
grepped every agent-facing runtime string / template / snippet for "until all_done"
without a plateau escape (none left) and "enrichment.done" without a channel
caveat — fixed the last one (launched_tracker_pending next_action). Now every
poll-path string states channel-aware done + plateau + no-wait identically.

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 03448caa07

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/snippets/server-instructions/quota-topup.md Outdated
…ta + granular-launch (wider sweep)

- server-instructions/quota-topup.md: the single-contact quota-refresh trigger now
  keys off the REQUESTED channel landing (email/phone_number present), not
  enrichment.done alone — which is already true for a contact enriched on the other
  channel, so a phone reveal could otherwise trigger the refresh early. [Codex]
- granular launch-bulk-enrichment.md.tmpl: same channel-aware qualifier on its
  "track via get_contacts" description.

Widened last round's sweep to ALL promptforge sources (not just the enrichment
tool files) — this quota snippet was the one it had missed. Remaining
enrichment.done mentions are field descriptions / candidate semantics, not
completion gates, and are correct as-is.

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bcf9fc6702

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
… message (match next_action)

The launched-mode `message` still opened with an unconditional "Do NOT end your
turn here — poll now", conflicting with the no-wait exception already in
next_action. Both are operator-facing, so a "kick it off, I'll check later"
request saw contradictory guidance. Both message branches (notification and
no-notification) now carry the same no-wait qualifier as next_action. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eee98084dc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/tools/enrich-contacts.ts Outdated
Comment thread packages/core/src/tools/launch-bulk-enrichment.ts
…o tool hints + gate lead-in

Round 15/16 rewrote the enrich_contacts and launch_bulk_enrichment hints to add
the channel-aware "done" rule but didn't carry the no-wait exception into them —
so those freshly-edited hints still said "don't end your turn, poll ~90s–2min"
with no background escape. Fixed both:
- enrich-contacts.ts: no-wait EXCEPTION → hand back leadId + contactId, re-check later.
- launch-bulk-enrichment.ts: no-wait EXCEPTION → say it launched, re-check via get_contacts later.
- notifications-inbox.md: the gate's opening "stay active" line now names the two
  exceptions up front so the lead-in isn't contradicted by the detail below.

Swept every "stay active / don't end your turn" agent-facing directive for the
no-wait qualifier — all now carry it (or lead with the exceptions).

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee8ca321dd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/composite/enrich-titles.ts
…uard + tracker-pending title filter

- enrich-titles.ts (REAL BUG): the aged-pending relaunch (round 12) did
  markFailed → re-reserve → unconditionally POST /launch. If a concurrent caller
  created the fresh reservation first, the re-reserve returns reused:true and both
  callers launched — a double paid launch for the same selection within the
  idempotency window. Now checks fresh.reused and defers to that reservation
  (returns already_launched, no second /launch). New test proves no /launch fires.
- enrich-titles.ts: the launched_tracker_pending fallback next_action now tells the
  agent to filter per-lead results to the enriched titles (job_title match) — the
  last spot the title-filter rule hadn't reached. [Codex]

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a1e23df59

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
…title filter in no-tracker fallback

Both are the message/next_action + branch-parity gaps:
- already_launched reuse message: add the no-wait qualifier (its next_action had
  it since round 15; the message still said "poll now" unconditionally). Same for
  the concurrent-guard reuse message.
- no-tracker fallback (message + next_action): add the title filter — count/report
  only contacts whose job_title matches the enriched titles (the tracker-pending
  and status paths already had it; this branch didn't).

Matrix-audited every launch-path string in enrich-titles.ts against the 4 rules
(no-wait / plateau / channel-aware done / title-filter); actionable directives now
carry every applicable rule.

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5287b41d31

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl Outdated
…unch, partial_failures plateau) + 2 no-wait variants

Real bugs:
- enrich-titles.ts: if markFailed throws, the aged pending row survives and the
  re-reserve returns THAT SAME row with reused:true — my round-19 concurrency
  guard then deferred to it, leaving a pre-launch-crash handle stuck 'pending'
  forever. Now the guard only defers on a GENUINELY NEW row (bulk_id !==
  staleBulkId); a same-id stale row relaunches (idempotent). New test.
- bulk-enrich-status.md.tmpl + enrich-titles.ts next_action: don't treat a flat
  overall_progress.done as a plateau while partial_failures is present — that's a
  transient per-lead fetch error (e.g. 429), not an unresolvable contact; keep
  polling / respect retry_after. (Code already excludes partial_failures from
  all_done; this closes the agent-facing plateau guidance.)

No-wait variants:
- no-tracker fallback message + tracker-pending fallback next_action now honor an
  explicit no-wait request (hand back lead_ids instead of forcing the loop).

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad5b1f6e86

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/core/src/composite/bulk-enrich-status.ts
Comment thread packages/core/src/composite/bulk-enrich-status.ts
…fication fast path

Codex round 22 (2 real findings, same class): on the fast path, include_contacts
fans out to getContacts, which uses allSettled — a rejected endpoint (429) becomes
[] instead of throwing, so a transient error was indistinguishable from "nothing
resolved" and the plateau rule could report those leads as permanently unresolvable.

- get-contacts.ts: additively expose _fetch_errors (endpoint + code + retry_after)
  when an endpoint rejects — ignored by existing callers, non-breaking.
- bulk-enrich-status.ts: the fast-path fan-out now builds partial_failures from
  both thrown errors AND getContacts._fetch_errors, and surfaces partial_failures
  on the return — mirroring the legacy path, so the agent's plateau rule honors it.
- New test: a 429 on a fast-path plateau contact read surfaces as partial_failures.

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 155d52b459

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +348 to +350
...(fastPartialFailures.length > 0
? { partial_failures: fastPartialFailures }
: {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep partial contact failures from ending polling

When a notification-backed job is terminal but the include_contacts:true fan-out hits a transient contact-read failure (for example a per-lead 429), this returns partial_failures while all_done still stays true because it only mirrors !inProgress. The stay-active guidance treats all_done:true as the terminal signal, so the agent can stop and report completion with missing contact data instead of retrying/respecting retry_after; the legacy path already excludes partial_failures from all_done, so the fast path should do the same or otherwise force a retry.

Useful? React with 👍 / 👎.


- **Previous turn / before an MCP restart, and the user has NOT asked about it** — don't poll for it in the background. Simply continue the conversation; the next time you call any tool, the completed-work entry appears in `_meta.notifications` (also on `leadbay_account_status.notifications`). This is the ambient push path — leave it to do its job. **But if the user explicitly asks for status or to "wait for it to finish"** (e.g. a multi-turn flow where a job was launched in a prior turn and this turn says "wait for enrichment to finish, then …"), DO poll its status tool now until done, exactly as for a this-turn job below — the ambient push only surfaces *completed* work, so it can't answer a live "is it done / wait for it" request while the job is still running.
- **This turn (you just launched it)** — the DEFAULT is: do NOT end your turn on the "launched" ack; stay active and poll the job's status tool in a loop until it reports done, then report the finished result yourself, rather than spinning forever or deferring the result to a later turn. (Two exceptions, detailed below: the user explicitly asked NOT to wait / to run it in the background; or it's a large qualification/import that's async by design — in those cases hand back the handle instead of looping.) Each status tool has its OWN terminal signal — poll until:
- `leadbay_bulk_enrich_status` → `all_done:true` — OR `overall_progress.done` holds steady across several SPACED polls (~15–30s apart) over at least ~90s–2 min of elapsed time (some contacts are unresolvable, so `all_done` can stay false forever). Don't call a plateau from the first few back-to-back reads — early on `done` sits flat while the backend spins up. Once the plateau is real, report what resolved and name what didn't.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude partial failures from shared plateau guidance

This shared terminal condition omits the partial_failures exception that leadbay_bulk_enrich_status now documents and returns. When a plateau/report read has transient per-lead fetch errors (for example a 429) and overall_progress.done stays flat, any prompt surface including this snippet can still tell the agent to stop and report those leads as unresolved instead of continuing to poll or honoring retry_after; mirror the status-tool guard here while partial_failures is present.

Useful? React with 👍 / 👎.

@ArtyETH06

Copy link
Copy Markdown
Contributor Author

Codex reviews are irrelevant at this point

@ArtyETH06 ArtyETH06 merged commit 32df76f into main Jul 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant