Skip to content

feat(telemetry): count the tool calls of the stage planner by outcome - #3679

Merged
dan-petty merged 10 commits into
mainfrom
feat/3240-count-stage-planner-tool-calls
Nov 5, 2026
Merged

dan-petty merged 10 commits into
mainfrom
feat/3240-count-stage-planner-tool-calls

Conversation

@dan-petty

Copy link
Copy Markdown
Owner

The stage planner calls read-only tools, and no metric shows which tools it calls or how each call ends. This change adds four instruments: the calls by tool and outcome, the answer size, the calls per run and the limit hits. Each tool sets its own outcome: empty for a call that found nothing, and error for a call that could not run. The change adds one line of tool counts to the trace comment, a panel to the devops-cli dashboard, and the alert RoadmapServiceToolUnused for a tool that no run called in 7 days. A promtool test covers the alert.

Closes #3240

Change: openspec/changes/archive/2026-11-05-3240-count-tool-calls-of-the-stage/

@dan-petty dan-petty added type/feature New user-facing functionality or capability addition scope/telemetry OpenTelemetry tracing spans, Prometheus metrics, and Jaeger labels Nov 5, 2026
@dan-petty

Copy link
Copy Markdown
Owner Author

Test results and review findings for #3240

Review findings

I checked each finding of the first review against the code. All seven were right. Each one is fixed in this pull request.

  1. empty could not occur, and a failed call counted as ok (two findings, one cause). I ran each tool of StageTools on edge inputs with the first rule (blank text is empty). 11 of 12 cases gave ok, for example No match., a path outside the repository, and GitHub is not available to this run. The one empty was git_show that returned '' when git ran out of time. Now each tool sets its own outcome with a pydantic-ai ToolReturn (ok_answer, empty_answer, error_answer), and RunTrace reads ToolReturnPart.metadata. A search with no match is empty. A refused path, a missing file or a failed GitHub read is error. A git command that runs out of time is now an error in every tool that runs git. The model reads the same text as before. I used a bare ToolReturn as the return annotation: str | ToolReturn made tools() 20 times slower (265 ms against 13 ms), because pydantic-ai builds the return schema for each tool.
  2. Plan text and code disagreed on a hard stop by UsageLimitExceeded. The code is right: the hook flags requests and window before they can stop a run, so a hard stop with no flag is calls. The proposal, the design and the tasks now say so. A test runs the case.
  3. seven cases of the promtool fixture. The fixture has eight. The text says eight, and the spec has the missing scenario "No run series exists".
  4. Patches of devops-cli code in the new tests. All five are gone. The limit tests call investigate with their own UsageLimits and window. The metric tests use the real tools and the real limits. A test of a git timeout uses process_fake.
  5. The job and instance check saw only an inline dict. It now reads a dict display, a name that holds a dict, and a dict that ** unpacks. I checked that it names a job label if I put one in tool_metrics.py.
  6. Sentences over 25 words. I split the text of the two counters, the alert row in k8s/README.md, and the sentence in the generator. docs/TELEMETRY.md is regenerated.

Fail-to-pass

uv run devops ci fail-to-pass --base origin/main exits 0: the replay of the new tests on the base tree gives 6 failed and 5 errored. The errors are imports of names that the base does not have, such as RunLimit. This pull request is a feature, so the replay is evidence and not a gate.

Checks on this host

@dan-petty
dan-petty marked this pull request as ready for review November 5, 2026 18:40
…s it (#3240)

A tool of the stage planner returns a ToolReturn whose metadata is ok,
empty or error. The run reads that value, so a search with no match is
empty and a refused path is error. A git command that runs out of time is
an error in every tool. The tests use the real tools and no patch.
…check (#3240)

The check named only an inline dict. It now reads a dict display, a name
that holds a dict, and a dict that ** unpacks, so tool_metrics is covered.
)

Each sentence has at most 25 words. The text of the outcomes says that the
tool sets them.
…sets (#3240)

The first design counted an answer as empty only for white space, and no
real tool gave that. The plan now has the tool set the outcome, and it
names the limit of a hard stop as calls.
@dan-petty
dan-petty force-pushed the feat/3240-count-stage-planner-tool-calls branch from 6221c86 to 012a5f3 Compare November 5, 2026 19:07
@dan-petty
dan-petty merged commit 45da6dd into main Nov 5, 2026
23 checks passed
@dan-petty
dan-petty deleted the feat/3240-count-stage-planner-tool-calls branch November 5, 2026 19:14
dan-petty pushed a commit that referenced this pull request Nov 5, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.63.0](v0.62.7...v0.63.0)
(2026-11-05)


### Features

* **roadmap:** let a negative search verify check more than one name
([#3678](#3678))
([5a4364c](5a4364c))
* **telemetry:** count the tool calls of the stage planner by outcome
([#3679](#3679))
([45da6dd](45da6dd))


### Bug Fixes

* **ci:** count tests and specs as hardening guardrails
([#3684](#3684))
([1d75506](1d75506))
* **security:** mask the user name of a URL with no password
([#3676](#3676))
([bc1cd9c](bc1cd9c))
* **service:** count each GitHub request with its HTTP status
([#3686](#3686))
([b39dcba](b39dcba))
* **telemetry:** Service counters read true across pods and repos
([#3680](#3680))
([05544ab](05544ab))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: dan-petty-release[bot] <346998822+dan-petty-release[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope/telemetry OpenTelemetry tracing spans, Prometheus metrics, and Jaeger type/feature New user-facing functionality or capability addition

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(telemetry): count tool calls of the stage planner by tool and outcome

1 participant