Skip to content

fix: relay Ask Proof comment to server ops endpoint so HTTP agents can poll it#38

Open
luckydem wants to merge 1 commit intoEveryInc:mainfrom
luckydem:fix/ask-proof-server-ops-relay
Open

fix: relay Ask Proof comment to server ops endpoint so HTTP agents can poll it#38
luckydem wants to merge 1 commit intoEveryInc:mainfrom
luckydem:fix/ask-proof-server-ops-relay

Conversation

@luckydem
Copy link
Copy Markdown

@luckydem luckydem commented Apr 8, 2026

Problem

invokeAgentOnSelection creates a ProseMirror mark via markComment and writes it into the local Yjs document. While a live collab session is active, the server blocks projection repair with blockedReason: recent_live_collab_lease — so any HTTP-polling agent calling /state, /marks, or the bridge endpoints will see empty marks and never receive the request.

The code comment already acknowledged this was incomplete:

// Import and use the agent session manager (will be created in Phase 1)
// For now, create a comment with the request for @proof to handle

But "Phase 1" was never wired up, leaving the Ask Proof UI with no backend path to an actual agent.

Fix

After creating the local mark, also fire a POST to /api/agent/:slug/ops with type: comment.add. This writes directly to the server's ops table in SQLite, bypassing the Yjs-to-projection pipeline. Any HTTP-polling agent sees the Ask Proof request immediately, regardless of collab lease state.

The local markComment call is preserved so the inline mark still appears in the editor.

fetch(`${shareClient.getApiBaseUrl()}/agent/${encodeURIComponent(slug)}/ops`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', ...shareClient.getShareAuthHeaders() },
  body: JSON.stringify({ type: 'comment.add', by: actor, quote: selectedText, text: `@proof ${prompt}` }),
}).catch((err) => {
  console.warn('[invokeAgentOnSelection] Failed to POST comment to server ops:', err);
});

Why this matters

Without this fix, the Ask Proof UI creates a strong expectation that an agent is listening — but nothing ever closes that loop. The feature is silently broken for any HTTP-based agent integration.

Testing

  1. Open a shared doc with an HTTP-polling agent connected
  2. Select text and use Ask Proof (right-click or ⇧⌘P)
  3. Agent receives the comment via GET /api/agent/:slug/events/pending within the same polling cycle

invokeAgentOnSelection only wrote a ProseMirror mark into the local Yjs
document. While a live collab session is active the server blocks
projection repair (recent_live_collab_lease), so HTTP-polling agents
cannot see marks written this way.

This change adds a fire-and-forget POST to /api/agent/:slug/ops
immediately after the local mark is created. The server ops table is
written directly to SQLite, bypassing the Yjs-to-projection pipeline
entirely, so any polling agent sees the Ask Proof request the moment it
is submitted.

The local markComment call is preserved so the mark still appears
inline in the editor for the user.
Copy link
Copy Markdown

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

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: cbe603703b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/editor/index.ts
Comment on lines +5423 to +5427
const body = JSON.stringify({
type: 'comment.add',
by: actor,
quote: selectedText,
text: `@proof ${prompt}`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve a single comment identity across local and /ops writes

This payload creates a second independent comment instead of mirroring the local one: markComment(...) already creates a local mark ID, but /api/agent/:slug/opsPOST /marks/comment assigns a new randomUUID() when no ID is provided, and projection merge preserves DB-only mark IDs (mergePreservedActionMarks), so both comments survive and appear as duplicates after sync. Reuse the local mark ID (or avoid dual-writing the same comment) so one user action maps to one comment record.

Useful? React with 👍 / 👎.

Comment thread src/editor/index.ts
Comment on lines +5436 to +5437
}).catch((err) => {
console.warn('[invokeAgentOnSelection] Failed to POST comment to server ops:', err);
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 Check /ops response success before treating request as queued

This call only catches thrown fetch errors and never inspects HTTP status, so non-2xx responses are silently ignored. comment.add can return a 409 anchor-not-found when the selected quote is newer than canonical markdown (a common live-collab state), so the backend request may fail while agent_manual_request_queued is still emitted, making Ask Proof look successful even though no pending event was created for polling agents.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant