Skip to content

fix(client): show partial graph answers to the CLI user and the agent - #50

Merged
coconutbird merged 2 commits into
mainfrom
fix/partial-graph-headers
Oct 26, 2026
Merged

coconutbird merged 2 commits into
mainfrom
fix/partial-graph-headers

Conversation

@coconutbird

Copy link
Copy Markdown
Member

Fixes #49.

semctx (feat/docstore-cutover) marks a degraded graph answer on HTTP 200 with X-Semctx-Graph-State, X-Semctx-Graph-Invalidation and X-Semctx-Graph-Repair. semctl did not read them, so a partial answer looked complete.

  • src/client/graph_state.rs: parse the headers; a per-call record of partial answers (PartialAnswers), capped at 8.
  • Client::send records a partial answer (or logs a warning without a record); a success answer is never retried.
  • CLI: semctl graph and semctl search print warning: the graph answer is partial (<reason>); <advice> on stderr, independent of RUST_LOG.
  • MCP (and the shared daemon): each non-error tool result gets a note: block with the reason and advice. semctl hook stays silent (its stdout is model context; adapters ignore its stderr).

Tests: retry record for all five reason/repair pairs, CLI output order, MCP note per call. Checks: fmt, clippy -D warnings, nextest (569 passed), rustdoc -D warnings.

semctx sends a degraded graph answer with status 200 and the headers
X-Semctx-Graph-State, X-Semctx-Graph-Invalidation and
X-Semctx-Graph-Repair. semctl did not read them, so a user got a
partial answer with no sign that it was partial.

The client now reads the three headers on each success answer. For a
partial answer it writes a warning with the reason to stderr. It keeps
the answer and does not retry it. Repair `none` (providers-unavailable,
flow-truncated) says that a retry returns the same result. Repair
`pending` (providers-loading, source-incomplete, graph-loading) says
that a later call can return more.

Fixes #49.
The first change wrote a partial graph answer only to the log. RUST_LOG
could hide it, and under `semctl mcp` it went to the log of the server
process, so the agent did not see it.

The client now puts each partial answer in a per-call record
(PartialAnswers) when the caller gives it one. The MCP call budget
carries the record of the call, and `call_tool` adds one
`note: the graph answer is partial (<reason>); ...` text block to a
result that is not an error. The shared daemon serves sessions through
the same handler. A client that a long-lived owner keeps gets no
record, like it gets no deadline.

`semctl graph` and `semctl search` print the answer on stdout and then
one `warning:` line for each partial answer straight to stderr.

`semctl hook` keeps no record: its stdout is the JSON context of the
model, and its stderr is dropped or not given to the model. The tool
that the agent calls next gives the note.

Refs #49.
@coconutbird
coconutbird merged commit 44a71d6 into main Oct 26, 2026
6 checks passed
@coconutbird
coconutbird deleted the fix/partial-graph-headers branch October 26, 2026 07:55
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.

Show partial graph answers: providers-unavailable, flow-truncated, providers-loading

1 participant